I'm working on a web application project using ASP.NET MVC3 and database in SQL Server. There is also a mobile application that uses the data from the same database via REST services. Here are some of my application's layers:
Model - ADO.NET Data Model, using Entity Framework
Data Access Layer - Repositories with queries to retrive data from database
Web application - MVC3 project, using repositories, loose coupling using Structure Map and DI, database context gets disposed at the end of the HttpRequest
Core - another layer between DAL and Service Layer, uses Repositories and exposes data to Service Layer. Sort of Business Logic Layer.
Service Layer - REST services, knows about Core layer but not about DAL. Maps the data to DTOs and exposes to the client
The problem I've got with such application architecture is loose coupling on the Service Layer. Service Layer has reference to Core layer. Core layer has reference to Data Access Layer and uses its repositories. Repositories do not have a default constructor though. They expect 1 parameter and its database object context (disposable object).
Using repositories directly on my website is not a problem. I'm using Structure Map and DI makes it loosely coupled. Each context gets disposed at the end of the HttpRequest.
The problem is that Service Layer and Core layer. I'd like to have loose coupling there as well but not sure how to achieve it? How to inject data context into those and make sure it gets disposed at certain moment? I'd like to hear some suggestions on how to put it all together.
Service Layer has reference to Core layer.
That's fine.
Core layer has reference to Data Access Layer and uses its repositories.
That ain't fine.
Your "Core" should be your domain, with business rules and logic. It should not have any dependencies.
Start from the bottom of the stack:
This is how we do it. We use a combination of interface-driven programming and dependency injection to handle the loose coupling.
Example flow:
ISomethingService
and resolves it, including any further down dependencies (service, repo, etc).ISomethingService
. ISomethingService
implementation (chosen by DI) calls method on ISomeRepo
.ISomeRepo
implementation (chosen by DI) calls EF/DB, returns "data-object" to service.The instantiation of these objects should be handled by your DI container. The only thing missing from the above which we use is a "Unit of Work", which essentially wraps the EF context.