I’m using NHibernate with RIA Services and Silverlight 4. I create DTOs for transferring the data via RIA Services rather than distributing my domain layer objects (as per Martin Fowler’s First Law of Distributed Object Design: “Don’t distribute your objects!”). The DTO objects are flattened down to two layers from five corresponding layers in the domain layer.
Here’s my problem. After making changes in Silverlight 4, RIA Services knows which DTO objects have been modified, but in the server-side update code I need to transfer the changes back to the “real” domain layer objects so that NHibernate can apply these changes back to the database. What’s the best way to do this?
Since the DTOs are intended to be lightweight, containing only the information that is needed on the client side, I obviously would not want to embed the corresponding domain objects inside the DTOs.
Here are a few of possibilities that I’ve considered:
1) Hold references to the domain objects within the DTO objects. As long as only the references get serialized and sent across the wire, not the entire referenced objects, then this might be a reasonable approach. Of course, the references wouldn’t be valid on the client side because they would point to non-existent memory locations, but at the end of the trip they could be used server side. (?)
2) Same as above but only save a reference to the domain aggregate root in the DTO object. Then use object relationship traversal to get to the other related domain objects.
3) Store the IDs of the domain objects in the DTOs and use NHibernate’s “Get” by ID or “Load” by ID functionality to retrieve the correct domain objects so that the updates can be applied.
4) Same as above but only use the “Get” or “Load” for the aggregate root and then use traversal for all related objects.
Perhaps none of the above is ideal and there is a better approach…
Whenever I build an access layer on top of ORM, I typically go ahead and put whatever the unique key is for the entity in the DTO, so that is tracked, and of course support for default(T) in the case of an add.
Then, when the object comes back to the server side, I can easily do a Load, marshall the changed values over from the DTO and then either let the session save it or perform an explicit save.
This would be your 3/4.
To answer your question at basic level - you may want to look into presentation model. Deepesh from RIA Services team has a good introductory blog post about it.
Also, you could use ID instead of reference (i.e. intrinsic, serializable value instead of app-domain-scoped object reference) and use [Association].
To answer at the next level, presentation model usage still involves work and additional types. It makes most sense when the shape of the model you want to see is substantially different from that on the server (whether a rich domain model or just DTO-based model). The increase in number of types and the need to map between them is the cost you pay for the flexibility. There are cheaper options that do less - e.g. non-public members, serialization directive [Exclude] etc that let you shape the code-gen'ed and serialized model. They may be worth considering. After all, the types on two sides of the trust boundary are very different by default (e.g. your types on the server vs code-gen'ed types on the client).
HTH
Dinesh
Related
I am learning some patterns, Unity of work / repository... There are some examples on web, but no one connects to more than one database.
In my applications almost always I have the need to get some object from a database (for example users) and some other object from another, how can I use the patterns ? (Since I am a novice on this subject an explicit example is a must)
Thank you!
As a general reference I advise you and anyone interested to visit http://martinfowler.com/eaaCatalog/index.html
which has a collection of UML and explanation over the most common Design Pattern for enterprises software
In your specific case Unity of work is particularly suited to work along with Data Mapper and Identity Map. I guess to understand 100% unity of work one must master also the other 2 pattern.
To answer your question I think you can create a unity of work and save it in a registry, so it is available all over the application. The unity must be a singleton since you need to ensure a central gateway to communicate with the database. Inside your unity of work you will have an identity map which is a collection of valued Objects in memory representing your model which is responsible to maintain the object states during all the application's operations. The unity will be used by your service layer to perform CRUD operations over the model and commit these changes.
To work with more databases I guess you need to leverage some sort of namespaced access to the object stored in the Identity map. You have the choice where to namespace: unity of work or identity map. The decision is really up to your application and use cases. You might need to connect to different DBs for splitting responsibilities between read and write or trying to integrate heterogeneous data sources.
An alternative would be to inject the DB object into the unity of work methods, in this case the application has 100% control over which database is used.
The repository pattern as far as I understand helps you to abstract to the storage of you model and it is particularly useful when you are working with heterogeneous data sources of you must provide such a flexibility to your application. Therefore I guess it is quite different from unity of work and Data Mapper layer.
Let me set up my LOB scenario.
I am re-writing our core business app. The requirements are that I create an internally usable app (I'd like to use Silverlight) that our employees use on a daily basis. I also need to provide a SOAP service that can be used to input orders, get invoices, etc.
I also will be doing this in pieces, so when I update a record in the new SQL Server database, I need to make sure to update our legacy SQL Server as well.
So, it certainly makes sense to create a DAL that will pull data from the new SQL server, as well as write back to 2 data stores.
It would also make sense to create a BLL that can be used by both Silverlight/RIA and the WCF web services.
I have created a data entity of the new database in it's own project and it is used in all the other projects. The problem here is that RIA seems to require that I create it right inside the ASP.Net project in order to get the metadata for Silverlight. Without this, I need to manually re-create the metadata for Silverlight to access it correctly.
My question then, should I create duplicates of the Entity Model? One for RIA and one for everything else? Is there a better way to do this? Should I just forego using RIA and have Silverlight access WCF services? Or should I just continue to duplicate the metadata in RIA?
We use entities for direct reference to storage and Data Transfer Objects (DTOs) which are almost identical for passing back/forth between BLL and WCF/GUI/etc. We map between the 2 using AutoMapper which means there's very little additional work but we don't have to worry about if a given entity is attached to the context/tracking state changes/etc...
Edit: You definitely want to keep your code as DRY as possible. Personally, I'd look at using DTOs above the BLL and either having 2 sets of repositories which are co-ordinated in the DAL (one RW, one W only). or even having Meta-repositories which handle the datasets on the 2 stores themselves.
If you're not already using it, Unity and IoC would be of real benefit to you here. You might also want to use one of the modular code patterns to allow you to register [n] data stores in different modes, so that when you finally want to retire the old store, you don't need to do much work.
I'd also question whether your entities need to be defined in ASP.Net - you may simple be able to reference the appropriate DLLs from your entity/DTO project and add the appropriate markup/config
I have come to a cross roads and can't figure out the proper way to get lots of data for a form onto a Silverlight / WCF RIA Services application. Imagine an order form that you can update fields about the order (Billing information, etc.) and also other information that is read-only, payments to the order, order items, etc.
The database is roughly Orders have Order Items and Order Payments. Order Payments have Payment Methods. There is a lot of other data associated with the orders table, but this gives you an idea.
With EF4, I can do Include statements to include child properties of the Order object, like OrderPayments and OrderItems, and get them all in one shot. But I haven't found a way to get child properties that point to objects (OrderPayments->PaymentMethod).
So would it be better to have lots of queries (declared explicitly in the XAML) calling each section of data individually (using domain data contexts), or is it better to build one massive view object that gets populated and sent to the client in one shot?
The biggest advantage of RIA services with EF4 is that the queries are lazily executed on the server. e.g. If you use paging on long lists of data only the page-size chunks are transferred. That is definitely the way to go. Not massive views with multiple sets of data.
When you need specific items, not covered by the automated relational links, add query methods to RIA and call those explicitly on your domain context.
The more I use RIA the more I like it. You just have to play nice with it :)
I'm still pretty new to Silverlight, quite new to WCF, and am trying to broaden my horizons into both. I'd like to learn what is considered to be good practices while doing so.
On the client side, I have a Silverlight application. On the server side, I have a database that the Silverlight application will be utilizing. In between the two (okay, it's server-side, but...), I have a WCF service that the client calls upon to get the data from the database.
I have created a class that is marked as a DataContract and is used by the WCF service. That class is an object model populated with data from the database. On the client side, when it requests and receives an instance of this class, it uses the instance data to instantiate and populate a client-defined object that has additional client-defined members.
It's my use of the DataContract that most worries me. To create an instance of an object to be serialized and sent, only to be pillaged for its data so another object can be created seems...inefficient. But if it's considered a good practice I can get past that.
I did consider going the route of a web handler (.ashx) and using a proprietary binary standard to communicate the data, but I think going the WCF route may be more applicable and usable in the future (thinking: job).
I don't see any particular problem with your approach.
In my mind what you're describing is the transfer of data from service to client as a DTO (data-transfer object), and then using that DTO to populate a view model object. It is also quite common for the DTO and view model objects to use varying levels of granularity in terms of the data they represent (typically DTOs will be more coarse grained), and the view model will contain behaviour that is specific to the UI.
You might want to look at tools and frameworks that help in the mapping between DTOs and view model objects. One of my favourites is AutoMapper.
I have some trouble getting my head around how to implement more complex operations in a Domain Service in RIA Services. This is all Silverlight 4, VS 2010 and .Net Framework 4 in Beta 2.
Goal
I wish I could create an operation on my LinqToEntitiesDomainService that would have a signature something like this:
public UnwieldyOperationResult PerformUnwieldyOperation( UnwieldyOperationParameters p );
The idea is that this operation takes a colleciton of parameters and performs rather complex operations which would update different instances and types of the entities that are otherwise manipulated through the DomainService CRUD functionality.
Problem
The immediate problem i hit is that does not seem to be allowed to pass the custom type as parameter to the method, and I suppose something along those lines go for the return value. I want to encapsulate the operation parameters in a DTO for clarity, and this unwieldy operation does not have any corresponding entity in the legacy database that I have wrapped with Entity Framework 4.0 model, which I am in turn basing the Domain Service on.
Is a domain service supposed to deal with only the types that are entities in the underlying EF model? Is it not designed to expose more complex operations like my UnwieldyOperation?
If so, can I build another service somehow that allows both the operation signature and to manipulate the entity framework?
I have understood that only one Domain Service can handle an entity from the model. This has led me to cram all the CRUD and now also the UnwieldyOperation into one Domain Service, although my first idea was to split the service into smaller parts.
If I'd get the operation to work with parameters and return value in the Domain Service, my next wish would be to have the entities that are already loaded in the domain context at the client refresh themselves.
Is there any efficient mechanism for such a thing?
How would you go about to do that?
What I have so far...
In short, this is what I have so far:
I have wrapped an existing legacy database
with an Entity Framework 4.0 model with as
little extra padding/code as
possible. This means right-click, add and generate from database.
I have implemented the simpler CRUD operations in the DomainService and I am using them successfully to display and edit straight forward data. I have some encapsulation of logic through ViewModels in client but I expose the Entity classes directly, but I think this is unrelated to my problem/question.
I have realized that I can't add the UnwieldyOperation in an as straight forward manner as I initially thought... Also I suspect/hope that I have misunderstood some aspects of the Domain Service mechanism, which has led me to the current situation.
One way to go?
Writing this down in a question like this gives me the idea that perhaps I'd go in this direction:
LegacyModelService expose the CRUD operations as I have already done.
Expose the Unwieldy operations in another service. Should I make that a RIA Doamin Service or just plain WCF?
Access the Entity Framework model from the new UnwieldyOperationsService and manipulate the data layer there.
Explicitly reload or refresh the client domain context for the LegacyModelService at the client to reflect the changes that may have resultet from the UnwieldyOperation. What would be a good way get this done?
Check out http://msdn.microsoft.com/en-us/library/ee707373%28VS.91%29.aspx for naming conventions over and above simple CRUD, maybe Invoke or Named Update operations would be suitable?