I want to create a repository class to separate out my data logic from my controllers. I am using a ViewModel to represent some data that will be filled with data from different tables.
Here are some questions I have:
- For a method like
GetAll()
, do I return anIQueryable<MyViewModel>
orIQueryable<Entity>
? If I return viewmodels, how do I cope with aGetAll()
that pulls thousands of records? - Do I create a constructor for my custom ViewModel class that takes the Entity as a parameter to do the mapping? (I'm still unfamiliar with automapper so just need an understanding on how to do this from a design point of view)
Again, my main concern is a method like GetAll()
which would pull many records. If I did a foreach loop to translate each Entity into a ViewModel seems like a lot of overhead. My thought was to put a reference inside the custom ViewModel class to the IQueryable<Entity>
to access from the collection, and have the ListViewModel just have indexers or something like that which reference the collection property.
There are many different ways to do this, but to start simply, I would return an
IEnumerable<T>
for your GetAll() method. However, you'll probably want to implement paging in some fashion. You might want to setup a generic repository that does your basic data access for most scenarios and returns an Enumerable. You could reserve a single method that should be reserved for more complicated queries and returns anIQueryable<T>
. The basic stripped down implementation might look like below.And the Interface would look like
The above can function as the beginning of a simple generic repository. Once you have your entities, you don't need AutoMapper, it just makes life easier as many ViewModels have the same properties as your entities. You can simply define a new ViewModel or List of ViewModels and map the properties on your own.
*That was quite a bit to type, sorry about any typos :)
IQueryable<Entity>
. The repository doesn't deal with view models. Think of the repository as something that is defined in a separate class library that doesn't reference your ASP.NET MVC application which is where your view models live. It is the ASP.NET MVC application that references this library.No. Don't create constructors in your view models especially if you want your controller actions to take those view models as action parameters (think of a POST action). The reason for this is that the default model binder will no longer know how to instantiate your view model and you will have to write custom model binders.
So AutoMapper or manually map.
Example with manual mapping which is what you could start with:
And once you get sick of writing this code move to AutoMapper:
or if you write a custom action filter that uses the OnActionExecuted event to pull the domain model that was passed to the view, map it to the view model using AutoMapper and substitute the model with the view model for the view, you could further simplify the repetitive code:
Don't be concerned about that. Pulling your records will be a magnitude slower than looping and mapping to the view model.
I think you may have a misunderstanding of the view model and it's purpose. You don't need to create a view model for every entity in your database, as it seems you want to do; you just create a view model for each view you want to render. Hence the term "view model"--it organizes the data in the form of a model that your view can be strongly typed to.
You wouldn't, for example, want to create a separate view model for every entity returned by a GetAll(). In a simple scenario of displaying a gridview of all records you would probably just need a single viewmodel with one property:
You would populate this view model in the controller
Have a look at this blog post by Rachael Appel for a really concise discussion.