Search code examples
c#asp.net-mvcentity-frameworkrepository-patternunit-of-work

How to structure projects with ASP MVC using Repository Pattern, Service Pattern, UnitOfWork, ORM (EF, NHibernate etc..)?


Although I am seeing lots of discussions about this topic, I can't find a very detailed answer regarding this. I want to know which should I put here and there.

Where should I put the IRepository interface. In the DataAccess or in separate project say "Repository"? How about other abstract Repositories that will extend IRepository<> like ICustomerRepository : IRepository ? Will they reside on the same project? How about the concrete implementation of CustomerRepository : BaseRepository, ICustomerRepository

And my POCO, where should I put them??

The UnitOfWork and Service Layers?

PS: Can all my Services just contain the UnitOfWork so I can call any repository? Is there a drawback there? or why would I want to use Repository over the UnitOfWork on Services?


Solution

  • Not a definite answer, hopefully set you in right direction

    If you plan to use ORM, framework would have taken care of Repository and UOW.

    Here is the layer you can begin with 1) UI - 2)Service agent - 3)service layer - 4)domain layer - 5)Repository

    Client to Service If only one client is going to use service, then service layer is unnecessary. May be Facade layer is enough which will run in same process as UI and if need comes to support multiple client application, it can be refactored to seperate service with relatively less effort. Abstract all service calls to service agent (Proxy). All communication from UI to service is through agent.

    If you are using something like server side mvc framework (ex: asp.net mvc), you may like to consider viewmodel for each screen. Since most of the screens contain data from different domain model (Order details + shipping info + customer details in one screen), view model will consolidate all the data to screen specific. In this case look at (.net) auto mapper for mapping between DTO (Data from service) and view models or build you own light weight mapper. If you are planning to use client side MVC for UI (ex: Angular) then you don't need to design view model explicitly. Whatever comes from service will be a model for your UI.

    Service to backend Service/facade layer - This will call appropriate methods on domain model. Design POCO (they model the domain), from domain model call repository for all CRUD. Internally Repository can use ORM. If you are not using ORM for whatever reason, you may have to build some generic code for mapping data from database/any other data store to domain model.

    Define class interfaces for all classes in domain layer, repository and service layer(anyway framework will force you to use interfaces for services). Remember to design coarse grained interface on service/facade otherwise you will end up with too many calls between UI and service

    Create a separate project for each layer, take one avg complexity use case, start implementing end to end making use of all the layers, entity types (view models, dto, domain models), mapper (Viewmodel-dto, dto-domain models). I would say keep all interfaces in separate project from concrete classes project as interface belongs to client. This will ensure client will not have direct dependency on concrete implementation project. Identify IOC container, use it to inject dependencies to its client. Ex: Use DI to inject domain model to classes in Service layer. Configure DI to inject concrete implementation in all layers (Service would use DI to get domain models, domain model would use DI to get repository). If you use DI it will make you code against interface which is good. Important thing is to refactor interface, classes, methods, structure till you feel overall structure looks fine because whatever high level design you implement for first use case will pretty much become template for all other use cases.

    Once you complete one use case, you and your team will spend more effort in learning/designing/discussing domain model (Read domain driven design by Eric Evans - Domain driven design author/creator). With so many things it can be quite confusing to think where to start and how to start. As I said start with project for each layer, add/remove as you refactor and you refactor very often.

    I assume project is some considerable complexity.