patterncsharpModerate
MVC Layered Project Structure
Viewed 0 times
projectstructuremvclayered
Problem
We are starting a new web project using C# / MVC4 and Entity Framework 5 for data access. I've decided to go with an n-layered approach for the structure of the project and I would like some feedback on my design decisions.
This is how the solution is structured:
DAL
The Data Access Layer is only concerned with simple CRUD like operations. I've decided to go with a repository approach. Here are the Repository interfaces:
After doing some research on using Entity Framework in web projects, the general consensus is that there should only be one
```
public class DbContextModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += context_BeginRequest;
context.EndRequest += context_EndRequest;
}
public void Dispose()
{
}
private void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext httpContext = application.Context;
httpContext.Items.Add(Repository.ContextKey, new ProjectEntities());
}
private void context_EndRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext
This is how the solution is structured:
- Project.Model (Class Library): Contains EF .edmx, entity models, and viewmodels
- Project.DAL (Class Library): Contains EF DbContext and Repository classes
- Project.BLL (Class Library): Contains business logic classes
- Project (MVC Project)
DAL
The Data Access Layer is only concerned with simple CRUD like operations. I've decided to go with a repository approach. Here are the Repository interfaces:
public interface IRepository
{
}
public interface IRepository : IRepository, IDisposable
where T : class, new()
{
T Add(T item);
T Get(object id);
T Get(Expression> predicate);
IQueryable GetAll();
IQueryable GetAll(Expression> predicate);
void Update(T item);
void Delete(T item);
}After doing some research on using Entity Framework in web projects, the general consensus is that there should only be one
DbContext/ObjectContext per request. So to create and dispose the single context for each request, I've written an HttpModule that injects the DbContext into the HttpContext.```
public class DbContextModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += context_BeginRequest;
context.EndRequest += context_EndRequest;
}
public void Dispose()
{
}
private void context_BeginRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext httpContext = application.Context;
httpContext.Items.Add(Repository.ContextKey, new ProjectEntities());
}
private void context_EndRequest(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication)sender;
HttpContext
Solution
Have a look on the Onion Architecture series by Jeffrey Palermo
How about this for a structure
-
Project.Domain (Class Library)
-
Project.Reports (Class Library)
-
Project.Data.Sql (Class Library)
-
Project.Service (Optional)
-
Project.UI.Web (MVC Project)
How about this for a structure
-
Project.Domain (Class Library)
- has no deppendencies on any other projects
- represents the core business of your app/service
- any external dependecies are abstracted away via DI (adapter pattern)
- you might want to define an IDataContext/ISession that abstracts away the storage mechanism for example
- contains both your entities and your business logic
-
Project.Reports (Class Library)
- references Project.Domain
- contains view models or projections or however you want to call them
- these models are crafted to serve the views in the UI
- i prefer to keep it separate from domain as ui requirements tend to change a lot more often then my core business
- you might want to have distinct dedicated view models for different platforms
-
Project.Data.Sql (Class Library)
- references Project.Domain
- contains EF DbContext, mappings, migrations
- the dbcontext implements the IDataContext/ISession defined in the domain
- do you really need repositories? Repository is the new singleton
- how about relying on the fact that the dbcontext already implements the unit of work and the repository patterns out of the box
-
Project.Service (Optional)
- web api or wcf would fit in here
- wires everything via a dependency injection container
-
Project.UI.Web (MVC Project)
- wires what it needs via a dependency injection container
Context
StackExchange Code Review Q#30843, answer score: 17
Revisions (0)
No revisions yet.