December 20, 2010 AutoMapper, NHibernate
December 20, 2010 AutoMapper, NHibernate
In my project we are using NHibernate and Automapper to automatically map heavy database objects to light DTO object that we send across the wire. This works just fine, unless you have to map light object received to the POCO class.
Accordingly to all normal recommendations and just good common sense. You would not expose properties of your database objects with setter. Because ORM should fetch object graph in consistent state. And when you want to set Customer for Order you would probably use SetCustomer() method for better visibility and in
public class Order { private Customer _customer = new Customer(); public virtual int OrderId { get; set; } public virtual DateTime OrderDate { get; set; } public virtual Customer Customer { get { return _customer;}} }
and in mapping you would write something similar to this:
public class OrderMap : ClassMap{ public OrderMap() { WithTable("`Order`"); Id(x => x.OrderId); Map(x => x.OrderDate, "OrderDate"); References(x => x.Customer) .Access.AsCamelCaseField(Prefix.Underscore) .WithForeignKey("CustomerId"); } }
as you can see, we set value for Customer using reflection deep inside of NHibernate. Also this approach ensures us that newly created Order will have default Customer object. But when we come to mapping OrderModel, which looks like below:
[DataContract] public class OrderModel { [DataMember] public virtual int OrderId { get; set; } [DataMember] public virtual DateTime OrderDate { get; set; } [DataMember] public virtual CustomerModel Customer { get; set; } }
OrderModel.Customer simply doesn’t map to Order.Customer, since AutoMapper doesn’t have access to write into that value. Sadly, but AutoMapper doesn’t have any convention like NHibernate .Access.AsCamelCaseField(Prefix.Underscore), which means that it will look for _customer.
And now! AutoMapper is much smarter than NHibernate. You don’t need any conventions you can simply put private set and you are good! So I did:
public class Order { private Customer _customer = new Customer(); public virtual int OrderId { get; set; } public virtual DateTime OrderDate { get; set; } public virtual Customer Customer { get { return _customer;} private set { _customer = value;} } }
Honestly I wouldn’t write this post if I had knew about this possibility before I started writing it. But since I wrote more than half of what you see I decided to finish the story. Enjoy or blame me. Anyway for myself I took following: sniff around features and components you are using, some of them have better ideas than others, your task is to absorb the best!
Markdown | Result |
---|---|
*text* | text |
**text** | text |
***text*** | text |
`code` | code |
~~~ more code ~~~~ |
more code |
[Link](https://www.example.com) | Link |
* Listitem |
|
> Quote | Quote |
nice features, thanks!
But.. Actually DTO classes should be just DTO classes, and you (as well as me and many other programmers, I guess) are mixing transfer objects with business logic objects :)
I think canonical way to do that would be to create your business objects from DTO classes and avandon DTO after that till the moment when you have to transder changed data back to server. What you think about that?
Yeah… you are right here as per me. On the client we have another set of business objects and after client received DTO from server it is then transferred to client's objects.
Sometimes we really mix BL and DTO classes…