N-tier architecture with service layer, business layer and Entity Framework

I just needed some kind of feedback / help on how I deal with the architecture of my application. My current decision structure looks something like this:

  • UI (Actual MVC Application)
  • Kernel (controllers and ViewModels only)
  • Services
  • Bll
  • Data (Entity DbContext infrastructure bound to Domain objects)
  • Domain (simple POCO objects)
  • Interfaces

Other things

  • Ninject to enter DbContext into the controller (for each request)
  • AutoMapper to display domain objects in ViewModel

All assemblies have a link to the "Interfaces" project, which, as the name implies, is nothing more than simple interfaces (i.e. IDbContext, IRepository, etc.).

The Services project links everything else. This is the only assembly that has a direct link to the Entity Framework.

I have provided the code below:

An example controller looks like this:

namespace Core.Controllers { public class HomeController : Controller { private IDbContext dbContext; public HomeController(IDbContext dbContext) { this.dbContext = dbContext; } public ActionResult Users() { UserService userService = new UserService(dbContext); var users = userService.GetAllUsers(); return View(Mapper.Map<IEnumerable<UserListViewModel>>(users)); } ... 

UserService Class:

 namespace Services { public class UserService { private readonly IDbContext dbContext; public UserService(IDbContext dbContext) { this.dbContext = dbContext; } public IEnumerable<User> GetAllUsers() { IRepository<User> userRepository = new Repository<User>(dbContext); UserBLL userBLL = new UserBLL(userRepository); return userBLL.GetAllUsers(); } ... 

Finally, a business level class:

 namespace BLL { public class UserBLL { private readonly IRepository<User> userRepository; public UserBLL(IRepository<User> userRepository) { this.userRepository = userRepository; } public IEnumerable<User> GetAllUsers() { return userRepository.Get(); } ... 

I am looking for some feedback / ways to improve. I notice that for basic tasks, my service-level methods will be exactly the same as the business-level methods (ie, Skip). I hope this abstraction will be useful for more complex tasks that may require calls to several business-level methods. Would it be better to incorporate business logic into the service level?

+6
source share
4 answers

With a quick glance, I don’t think your service and controller / kernel level should have a db context entered into them that way. They actually do not directly depend on it and do it in such a way that some combinations are not perfect. At the basic level, a user service must be introduced, and the user service and the BLL must have a nested repository. The repository must have the dbcontext entered by your DI map and not be passed as a dependency.

+9
source

Why do you use dependency injection when you create dependencies directly in the service?

 public IEnumerable<User> GetAllUsers() { IRepository<User> userRepository = new Repository<User>(dbContext); UserBLL userBLL = new UserBLL(userRepository); return userBLL.GetAllUsers(); } 

Btw. why do you use so many layers when they really don't do anything? Your sample code just shows that using context in the controller will directly lead to the same result without three useless shell layers. This may just be the problem of your example, but each layer should add some added logic. If you just use it to call something at a lower level, you are likely to unzip your code. This is called onion architecture. This is also the reason that a good practice is to add a layer when you need it, and not up.

+4
source

Please check this: http://www.primaryobjects.com/CMS/Article122.aspx EF repository template + work template. As for the other layers, it really depends on the application and what it needs to complete. Please provide more information about what you are trying to do.

+1
source

Some of the improvements in project organization and layer design can be made with emphasis on correctly obtaining domain objects.

You said that you have simple POCO objects like Domain, but Domain objects must be those that have all the "Status and behavior" . This means that you do not need to separate the BLL and Domain assemblies. Once domain objects are defined, EF can be used to create context and entity classes (which are not Domain classes if there are no additional steps compared to your domain object, but still their use may be good for future requirements).

Another minor point is that the presence of interfaces distributed at the domain and service level is better from the point of view of understanding each level individually.

0
source

Source: https://habr.com/ru/post/923513/


All Articles