This document discusses building an enterprise application using Silverlight, NHibernate, and following CQRS and MVVM patterns. It recommends using OData to implement the query model in CQRS and NHibernate for the domain model. It then covers implementing the front-end using MVVM principles in Silverlight, including using view models, commands, and an event aggregator for communication between view models. Demo code is provided for various aspects like OData queries, NHibernate usage, implementing a base view model, locator pattern, MEF, and unit testing view models.
Building an enterprise application with Silverlight, NHibernate and CQRS
1. Building an enterprise application with Silverlight and NHibernate Gill CleerenMicrosoft Regional Director/MVP ASP.NETVisugUsergroup lead - Ordina www.snowball.be Bart Wullems MCT, MCPD Application Architect Ordina bartwullems.blogspot.com
2. Agenda Building the foundation CQRS OData NHibernate Building the front-end in Silverlight MVVM What is MVVM? Why and why not The parts of MVVM Implementing MVVM principles Demo Finding your VM using MEF Commanding Communication between VMs
7. CQS Defined Bertrand Meyer (via Wikipedia) “Command Query Separation” “every method should either be a command that performs an action, or a query that returns data to the caller, but not both. In other words, asking a question should not change the answer.”
8. CQRS defined Meyer: Separate command methods that change state from query methods that read state. Greg Young: Separate command messages that change state from query messages that read state. Can have significant architectural implications
10. Queries Simple Query Layer Simple views or sprocs or selects from denormalized tables Simple DTOs, no mapping needed Don’t go through the Domain Model, as it pollutes it ViewModel per query perhaps Why should the data come across 5 layers through 3 model transformations to populate a screen? (Udi) Synchronous, no messaging needed
11. Commands Commands capture intent, DTOs don’t CustomerDTOvsCustomerChangedAddressCommand Handler per command Can be validated outside of domain entities This is why domain entities are never invalid, commands that would produce invalid state are rejected
12. Commands Separate Data Modification Make preferred Change address A generic DTO could do these things, of course, but after the fact, how do you know what actually happened? UI Implications Grid-like screens don’t work Commands require specific intent
16. A RESTful Interface for Data Just HTTP Data as resources, HTTP methods to act on it Leverage caching, proxies, authentication, … Uniform URL syntax Every piece of information is addressable Predictable and flexible URL syntax Multiple representations Use regular HTTP content-type negotiation AtomPub, JSON
17. Model and Operation Semantics Underlying data model Entity Data Model Entities Resources AssociationsLinks Operation semantics Mapping of HTTP methods GET Retrieve resource POST Create resource PUT Update resource DELETE Delete resource
19. WCF Data Services HTTP Data Services Runtime Reflection Provider .NET Classes [+ LINQ provider] Data Source(IQueryable)
20. oData and Silverlight Accessing Data Services Silverlight ClientHttp stack still an option Data Services Client more usable as it knows the details of the data service interface Features Full abstraction on top of the service – no need to deal with HTTP, serialization, etc Data as objects with automatic change tracking LINQ for queries Data-binding friendly interfaces Work same-domain and cross-domain
24. NHibernate Full-featured ORM solution Open source Based on Java’s Hibernate framework Uses XML(by default) to map tables/columns to objects/properties
30. Convention over Configuration FluentNHibernate http://fluentnhibernate.org Replaces XML mappingbyfluentmapping XML configurationbyfluentconfiguration Advantages Type safety Removestedious XML mappings Intuitive interface Conventions
35. Understanding MVVM MVVM : is an architectural pattern created by John Gossman from WPF team is a variation of MVC pattern is similar to Martin Fowler’s PresentationModel pattern works because of Silverlight data Binding & commanding is typically used in WPF/SL-applications to leverage the power of XAML, so that Devs and Designers can work together easier 35
38. Why MVVM Better SoC (Seperation of Concerns) More maintainable Model never needs to be changed to support changes to the view ViewModel rarely needs to be changed to support changes to the view More testable ViewModelis easier to unit test than code-behind or event driven code Eliminates the need to do code behind which leaves the UI all in XAML 38
39. Why MVVM Because the framework (SL & WPF) have the power to support it Databinding/DataContext Increases the "Blendability" of your view
40.
41. Too much code neededINotifyPropertyChanged Commands 40
60. ViewFirst Based on XAML mostly The View has a relationship to its ViewModel (usually through data binding). DataContext={Binding ...} Available at design time (Blend support) 54 View <UserControl.DataContext> <dive:PageViewModel /> </UserControl.DataContext>
61. ViewModel First The ViewModel creates the view usually through an IoCcontaineror MEF 55 View Model public MyViewModel(IMyViewmyView) { myView.Model = this; }
62. How to implement this? Locator pattern Implemented through a class that contains all VMs as static properties An instance is then made available as Resource All Views can bind, no code needed in View Clean way Not good since all VMs need to be known upfront Property for each available VM Difficult if application is MDI-like (more than one instance available) 56
64. How to implement this? MEF Based on Import: class says it needs an instance of a specific type Export: class says it wants to be made available for composition Composition: MEF links imports and exports together Can create one shared instance or dynamic number thereof Solves earlier problem Easy for testing and mocking 58
66. Commanding Instead of having event handlers in code-behind, we use commands SL4 has the ICommand interface Execute method CanExecuteproperty CanExecuteChangedevent Way to create commands: Write ICommand implementation Create instance on VM Bind Command property of control to this instance 60
67. Commanding Commanding is supported on ButtonBase Button, HyperlinkButton Not on others like ComboBox SelectionChanged Can be solved with event triggers Can be added on every event Part of System.Windows.Interactivity Can be bound to every control
69. Communication 63 View Model View Model View Model View Model View Model View Model View Model View Model
70. Communication 64 View View XAML XAML Code-Behind Code-Behind View Model Data Model View Model State + Operations Data Model State + Operations Message Publish messages View XAML Code-Behind Subscribe to messages Event Aggregator View Model Message State + Operations
71. Communication VM’s need to be able to talk to each other, eg: send messages to each other Not a good idea to have each VM reference all other VMs Solution: Event Aggregator/mediator/messenger VM can register to receive messages of a certain type (for example string messages) Another VM can register with the same messenger to send messages This allows both VMs to communicate with each other without tight coupling 65
74. In View’s constructor, check DesignerProperties.IsInDesignToolUnit testing VMs can easily be unit-tested Silverlight Unit Testing Framework ships with Silverlight 4 Can be used from the browser No real way to integrate with automated testing (MSBuild) yet 67
76. Summary CQRS Gives the necessary level of scalability and maintainabilityforenterpriseapplications oData is greatfor the query part NHibernate rocks for the command part MVVM Create better testable applications Works for both Silverlight and WPF
TraditionalN-tierleavestoomuchquestionsunansweredHow to handle the gap betweenvisualization and domain specification(how do youchangeyourrich domain model intosomethingthatcanbevisualized) Most business logicgotscatheredaround
Ons query model tonen(is ook opgebouwd met nHibernate)DataServiceKey attribuutTravelPlannerQueryContextTravelPlannerQueryServiceDataServiceKey even aanpassen naar CityNameAantal voorbeeld urls tonen:/Cities/Cities(‘Paris’)/Cities(‘Paris’)/CityNameCities(‘Paris’)/name/$value/$metadataLinqPad tonen voor complexe gevallen