FluentNH mapping of a "deep" relational model to a "flattened" domain object
Here's the story: a Site (physical location of interest) has zero or more Contacts. Those Contacts are people associated with a Company who are authorized to deal with matters regarding the Site.
The schema looks like:
Person -< CompanyContact -< CompanySiteContact >- Site
||
| -< PersonPhone
|
-< PersonAddress
My entry point is Site. I need the list of Contacts. There is very little field data of interest until you get to Person. So, I'd like to collapse Person, CompanyContact and CompanySiteContact int开发者_JAVA技巧o one domain class.
The options I've come up with:
Create one domain class and use joins in the FluentNH map to flatten the layers as it retrieves the data . It never sounded simple, and I'm running into problems with the multi-level join (if A joins B joins C, you can't specify the join to C within the join to B). I think, however, that if it's possible to specify the joins, that's just a one-time thing and so this will end up being the most maintainable solution.
Replicate the deep model in a set of "DTOs" that map 1:1 to the tables and can be passed to the constructor of a "flat" domain model. It works, but it feels like cheating (there is no problem that cannot be solved with another layer of abstraction, EXCEPT for having too many layers of abstraction), and my instinct tells me this will somehow eventually cause more problems than it solves.
Replicate the domain model 1:1 with the schema and use pass-through properties on CompanySiteContact to access properties down in the depths of a Person record. Again, works now, but it doesn't really solve the problem, and every new property that becomes of interest will require changes to the mapping, the actual domain class, AND the top-level domain class. Not very SOLID.
So, the Q is, how would I structure the mapping? Like I said, I'm not able to specify a join in a join. I think the way I have to do it is map the PK of each table, and use it in the next join from the top level, but I'm not exactly sure how to set that up (haven't used FluentNH to set up anything close to this complex before).
I'd recommend creating your domain model to closely match your database. From there I'd create DTOs and use AutoMapper to do the flattening. Easy.
Thanks to James for his answer; +1, but I don't think AutoMapper is necessary at this juncture, and I'm a little uneasy at including something that does the job quite that "automagically". I thought of a few more options:
Set up a view in the DB. This will work because due to business rules, the contact information is read-only; the app I'm developing must never update a contact directly because a different department maintains this rolodex.
Map my domain 1:1 as James suggested, but then use a Linq query to flatten the model into a DTO. This query can be encapsulated within a helper of the Repository, allowing developers to query the DTO directly using the same methods on the Repository as for other classes. It's more complex than the view with the same result, but it doesn't require schema changes.
I'll probably go with the first option, and resort to the second if necessary.
精彩评论