Reputation: 36204
I need to separate ViewModels in my MVC project from my business models (Data access layer) which lives in a separate library.
Assume that I have Database Access Layer classes in a separate library. Our primary project (MVC) does know nothing about those classes and they talk to each other through an Interface. It’s easy enough to use IOC and resolve dependency injection using Ninject or something, right?
Now DataAccessLayer contains class named Car with properties Engine and Wheel. In my MVC project (which doesn’t know nothing about DataAccessLayer and its classes) I need to use some Car objects. So I have another Car class (it’s just a pure ViewModel) and it has the same properties – Engine and Wheel (of course in real app there will be some differences between model and viewmodel, for the sake of simplicity let’s ignore that)
IDataAccessLayer Interface has a method called IEnumerable GetAllCars() that returns list of DataAccessLayer.Car objects.
Now I need to create MVCProject.Car collection, iterate through IEnumerable which was returned by GetAllCars(), on every iteration I need to create a new MVCProject.Car object, populate Engine and Wheel properties, and finally add that object to the Collection.
So: everytime I have to create almost the same structures and somehow manage them in different places.
Here is the problem, see? Or it isn’t? I feel like it will end up into big mess if I don’t change that. Don’t repeat yourself principle violation as it is. Tell me please how to make it right. Using I don’t know proxies or prototypes or maybe some other design pattern which I suck anyway. Or some sort of a tool like Ninject (which I only know how to use as IOC container) or Automapper or whatever, which I probably will suck even more than I suck in design patterns.
Upvotes: 2
Views: 1032
Reputation: 27811
I also don't see much of a reason to keep the DAL separate from the MVC layer. In case you're interested, here is the layout that I've used for multiple project and I find it is very usable and flexible.
DataObjects Basic objects with only properties. Also includes enumerations which the DataObjects use.
DataAccess Inherit from DataObjects and add GetByPrimaryKey, GetByForeignKey, GetByUniqueIndex, GetAll, etc., etc. Also contains the Caching layer where you would find StateCache, CountryCache, etc. for quick access to frequently used things. The "GetBy" methods will utilize the caching layer whenever possible.
Logic Static classes, one for each DataObject\Access type. Includes logical work other than simple fetches as detailed in the DataAccess layer.
Web\Front-end UI works with DataAccess and Logic layers to get and update objects as well as call other defined logical APIs.
I use my own custom-made code generator to generate 98% of this code (except the UI layer).
Upvotes: 3
Reputation: 36204
I found a way to make it really ugly :)
The Goal: Caller doesn't know nothing about Model Entities at DataAccessLayer, and gets all the data through the interface. How to get the data without manual mapping between Model and Viewmodel? Through reflection.
public IEnumerable<T> GetCars<T>()
{
var lst = new List<T>();
_data.GetTable<Cars>().ToList().ForEach(x =>
{
var newCar = Activator.CreateInstance<T>();
typeof(T).GetProperty("Engine").SetValue(newCar, x.Engine, null);
typeof(T).GetProperty("Wheel").SetValue(newCar, x.Wheel, null);
lst.Add(newCar);
});
return lst;
}
It Works. But the biggest question here is it fair and considerable architectural decision? How the performance will be affected in a real life app?
Upvotes: 0
Reputation: 83366
It sounds like your MVC library should know about your data-access library, shouldn't it?
Or, if you really want to keep your MVC and DAL libraries separate, you could always add a third library with references to both MVC and DAL. Then it could handle retrieving cars from the one library, and converting them to the other.
But again, I don't see why your controllers (or ViewModel, from what you've described) shouldn't have access to the DAL. Your car ViewModel would retrieve instances of Cars from the DAL, and go from there. So long as the way in which it receives the cars is coded through an interface, you should be able to stub that out later for your unit tests.
EDIT
So it looks like you think you'll be changing the entire DAL around later, and you want to minimize the difficulty of that? If that's the case, you might look at the adapter pattern. You would pass all your DAL objects to adapters, which would return to you objects in your business layer. Then, if your DAL changes, you just update your adapters.
Upvotes: 2