This is sort of a generic question in regards to mapping between data entities, domain objects, and ViewModels. I may not be asking it right but hopefully I can make some sense of it. Below is a simplified problem.
Pretend I have an Entity Framework model which maps 1:1 to my database tables, but my domain objects may not be identical, and my ViewModel is drastically different again. As a pseudo-example:
Database/EF Entities:
- MembershipAccount
- MembershipAccountExtraInfo
Domain:
- Account
- Profile
- Preferences
ViewModel:
- UserProfileModel
Let's say I need to display a UserProfileModel which has: Username (from MembershipAccount), SignupDate (from MembershipAccount), FullName (from MembershipAccountExtraInfo), and TimeZone (from MembershipAccountExtraInfo)
What sort of relationships might I need here, and what sort of mapping mechanisms? Is it common to have something like an AccountMapper that takes both a MembershipAccount and MembershipAccountExtraInfo and returns an Account? I'm a bit stuck on the mapping when several objects are needed to create a single domain entity, and vice versa.
If it helps: I'm designing an API for managing User Accounts, User Profiles, User Preferences, etc. but the database tables are all over the place. A single User Profile might need to be created from data spanning 4-5 tables and 2 databases. There is no 1:1 mapping between my database tables and any (logical) domain objects.
Thanks!
I like to work keeping my domain objects as close to the objects that they represent as possible. What I mean by this is that if an account has preferences, then the domain
Account
object should contain aPreferences
property, most likely represented by a collection ofPreference
objects. If nothing else, this helps the users understand the data structure of the application easily.As for constructing the view models, that's the easiest bit... you add just properties for anything that is required. What types of properties you would need would really depend on how you have structured your domain objects.
If your view has the requirements that you mentioned in your question and you modelled your domain objects closely on the objects that they represent, then by the sounds of it, you would just need an
Account
object because that would contain thePreference
andProfile
objects inside it.Finally, the only 'mapping' that needs to be done can be done with a
LinQ
query using the Entity Framework. It is at this point that I join the tables and pull whatever data that I need for whichever object I am working on. Here is an example of instantiating objects from data from three tables (usingLinQ2SQL
):UPDATE >>>
Extending my
AudioTracks
example and working backwards, theGetAudioTracks
method is in a project calledDataProviders
. It is called from aGetAudioTracks
method in aDataController
class which just adds user feedback and re-try options. That in turn is called by aTracksModel
in theModels
project which just contains a subsection of methods from theDataController
class that relate to the various types of tracks in the application.Finally, the
AudioTracksViewModel
in theViewModels
project calls theTracksModel.GetAudioTracks
method upon initialisation which happens when theAudioTracksView
is loaded by the user. TheAudioTracksView
has aListBox
on the left containing all of theAudioTrack
objects that meet the users search and/or filter selections. The right of the screen has the fields for the selectedAudioTrack
. Here is what it looks like (if the link seems broken, you can view the image here):The more transparent fields with an edit
Button
on the right are read only fields connected to collections. The editButton
opens a dialog to let the user enter multiple items, which are then summarised in the field. All of the objects in the application have similar views of more or less complexity.