9

I'm having a little bit of trouble conceptualizing how to architect an MVC App with Entity Framework into a n-tiered app.

The normal, textbook 3-tiered app should look something like

Data Access->Business Logic->Presentation

The presentation shouldn't know anything about the data access. With EF, ALL layers need to know about the model. So my architecture now looks more like

Data Access->Business Logic
     |               |
      ---------------
             |
            MVC

Am I missing something here or am I thinking about this in the wrong way?

Should I be thinking of EF itself as the data access layer and put the entities in the business logic?

Scottie
  • 11,050
  • 19
  • 68
  • 109
  • This is a good read on architecture for .NET applications and has a section on MVC: http://www.amazon.com/Microsoft%C2%AE-NET-Architecting-Applications-Pro-Developer/dp/073562609X – Hector Correa Oct 19 '11 at 12:39

3 Answers3

9

Well, I suppose your question is, how to architect "layers" in MVC application. Take a look at this simple architecture, I use it for my MVC apps and it seems to be clean and efficient.

  1. project in solution - business model - simple class library full of POCO classes representing business domain. You can use data annotation here, metadata classes for validation logic, etc.

  2. project - EF-based repositories - another simple class library; here is defined context (EF code first is great, but you can use EF database first or model first - you just have to add POCO T4 template to the business model class library, no big deal) and set of classes - repositories

  3. project - i usually call it "ServiceLayer" or so (i am open for suggestion for better name :) - it contains only interfaces, for repositories and other services (implemented in separate projects) which will my MVC (or any other technology) based application use; repositories from 2.project implement these interfaces

  4. project - MVC website. It uses dependency injection (build in DependencyResolver, and i love to use Ninject container) for mapping repositories (and other services); Then you can use constructor injection into controllers, or some "lazy" approach (see below)

It looks something like this :

Skinny controller :

public class SomethingController : BaseController
{
    public ActionResult DoSomething(SomeBusinessThing input)
    {
         if (ModelState.IsValid)
         {
             var result = CustomerRepository.DoSomeBusinessLogicAndPersistenceAndStuff(input);
             return View(result); // you can use AutoMapper here, if you dont want to use business object as viewmodels
         }
    }
}

My repository "property" is inherited from my BaseController :

public class BaseController : Controller 
{
    // ... other stuff used by all (or multiple) controllers

    private ICustomerRepository _customerRepository;
        protected ICustomerRepository CustomerRepository
        {
            get
            {
                if (_customerRepository== null)
                    _customerRepository= DependencyResolver.Current.GetService();
                return _customerRepository;
            }
        }
}

You can use this "lazy" DI if your controller use many services, but only 1-2 per action, so it would be kind of inefficient to inject all of them with constructor. Somebody could tell you are "hiding" dependency this way, but if you keep all this stuff in one place - BaseController, its no big deal.

Well, implementation of repository is really your business. MVC application dont even know you are using EF, it knows only interfaces of services and doesnt care about underlaying implementation (which you can switch any time later if you need to !)

Conslusion :

  • Controllers are skinny - no business logic

  • Model is FAT - and in this case, repositories encapsulate all the business logic (you can sure use other type of services as well, for example some calculators for processing etc., remember, MVC doesnt care, knows only interfaces)

  • ViewModels are input for Views (and ViewModel can be your business model directly, or you can use AutoMapper for creating "pure" ViewModels)

rouen
  • 5,003
  • 2
  • 25
  • 48
  • do you have sample project based on the above architect? – Nick Kahn Aug 29 '13 at 01:49
  • Very informing answer. BTW, the 3rd layer is called "application layer" I believe. – Ghasan غسان Mar 31 '15 at 02:28
  • @rouen In `SomethingController` instead of performing business logic in Repository class (`CustomerRepository.DoSomeBusinessLogicAndPersistenceAndStuff`) *which gives repository class **2 responsibility** * it would be better if there will be `BusinessLogic`. so schema looks like this `controller` -> `businessLogic` -> `data`. – tchelidze Jan 08 '17 at 10:06
5

You can think of your EF entities as data objects, and have separate view-models that are passed into the views. Data from your EF objects can be used to populate the view models (libraries like AutoMapper are useful here). This way, your views never have a direct dependency on EF objects, only on your view-models.

Chris Fulstow
  • 41,170
  • 10
  • 86
  • 110
  • I'm assuming a view model isn't the MV in MVC, right? That a view model is something with EF? – Scottie Oct 19 '11 at 03:48
  • A view-model is a standard class that's independent of your data access library. It's a dumb object that contains the data that'll be used by the view. – Chris Fulstow Oct 19 '11 at 03:56
  • @Scottie - the data objects in EF are specific to the EF (if you want to maintain clean code separation), so don't use them outside of your data layer. – Adrian K Oct 19 '11 at 07:53
0

I can recommend you really good (I think) book about domain driven architecture design on .NET platform. Book si called N-layered domain driven architecture guid with .NET 4.0. In book is explained how to create good architecture with EF and MVC (and many other stuff like Silverlight, IoC with Unity etc.).

Book can be downloaded on this address:

http://msdn.microsoft.com/es-es/architecture/en/

Also sample application is very interesting:

http://microsoftnlayerapp.codeplex.com/

Best way how to create entities for EF is creating POCO classes independent on persistent layer. These domain entities are included in Domain (Business) logic layer.

In book is also explained that application should be devided into more layers, they explaining Presentation, Appliaction, Domain, Infrastructure (data persistence mostly), Cross-cutting and Distributed services layers.

Michal
  • 1,324
  • 2
  • 16
  • 38