views:

188

answers:

2

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…

+2  A: 

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.

Jeremy Likness
Don't forget that you may need to handle the version field as well to avoid concurrency issues.
Sam
Jeremy and Sam, Thanks for the tips!
MylesRip
A: 

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

Dinesh
MylesRip