具有服务层,业务层和实体框架的N层架构

时间:2021-11-11 02:21:47

Just wanted some feedback/help with the way I'm architecturing my application. My current solution structure looks something like this:

只是想要一些反馈/帮助我正在构建我的应用程序的方式。我目前的解决方案结构如下所示:

  • UI (Actual MVC application)
  • UI(实际MVC应用程序)

  • Core (only Controllers & ViewModels)
  • 核心(仅控制器和ViewModels)

  • Services
  • BLL
  • Data (Entity framework DbContext, mapped to Domain objects)
  • 数据(实体框架DbContext,映射到Domain对象)

  • Domain (Simple POCO objects)
  • 域(简单POCO对象)

  • Interfaces

Other stuff

  • Ninject to inject DbContext into Controller (per request)
  • Ninject将DbContext注入Controller(每个请求)

  • AutoMapper to map Domain objects to ViewModel
  • AutoMapper将域对象映射到ViewModel

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

所有程序集都引用了Interfaces项目,顾名思义,它只不过是简单的接口(即IDbContext,IRepository等)。

The Services project "ties" together everything else. It is the only assembly which has a direct reference to the Data access layer (Entity Framework).

服务项目将所有其他项目“联系在一起”。它是唯一一个直接引用数据访问层(实体框架)的程序集。

I've provided some code below:

我在下面提供了一些代码:

An example of a Controller looks like this:

Controller的示例如下所示:

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));
        }
        ...

The UserService class:

UserService类:

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, the business layer 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'm looking for some feedback/ways to improve. I notice that for basic tasks, my service layer methods will be exactly the same as the business layer methods (i.e. "pass through" functions). What I'm hoping is that this abstraction will be helpful for more complex tasks which may require calls to multiple business layer methods. Would it just be better to include business logic in the service layer?

我正在寻找一些反馈/方法来改进。我注意到,对于基本任务,我的服务层方法将与业务层方法完全相同(即“通过”函数)。我希望这个抽象对于可能需要调用多个业务层方法的更复杂的任务有所帮助。将业务逻辑包含在服务层中会更好吗?

4 个解决方案

#1


9  

From a quick glance, I don't think your service and controller/core layer should have the db context injected into them in this manner. They don't actually directly depend on it and doing it in this manner causes some coupling that is not ideal. The core layer should have the user service injected and the user service and BLL should have the repository injected. The repository should have the dbcontext injected by your DI framework and not passed in as a dependency.

从快速浏览一下,我不认为您的服务和控制器/核心层应该以这种方式将db上下文注入其中。它们实际上并不直接依赖它,并且以这种方式进行它会导致一些不理想的耦合。核心层应该注入用户服务,用户服务和BLL应该注入存储库。存储库应该具有由DI框架注入的dbcontext,而不是作为依赖项传入。

#2


4  

Why are you using dependency injection when you are creating 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 are you using so many layers when they actually do nothing? Your example code just shows that using context in controller directly would produce the same result without three wrapper useless layers. It may be just problem of your example but each layer should bring some added logic. If you just use it to call something on lower layer you are most probably overarchitecting your code. This is called onion architecture. That is also a reason why it is not a bad practice to add layer once you need it - not upfront.

顺便说一句。当他们实际上什么都不做的时候你为什么要使用这么多层?您的示例代码只显示直接在控制器中使用上下文将产生相同的结果,而没有三个包装器无用的层。这可能只是你的例子的问题,但每一层都应该带来一些额外的逻辑。如果您只是用它来调用较低层的内容,那么您很可能会对代码进行过多的构建。这被称为洋葱建筑。这也是为什么在需要时添加图层并不是一个不好的做法 - 而不是预先。

#3


1  

Please check this out: http://www.primaryobjects.com/CMS/Article122.aspx EF Repository pattern + Unit Of Work pattern. As for your other layers, it really depends on the application and what it needs to accomplish. Please provide more details on what you're trying to do.

请查看:http://www.primaryobjects.com/CMS/Article122.aspx EF存储库模式+工作单元模式。至于你的其他层,它实际上取决于应用程序以及它需要完成的任务。请提供您正在尝试做的更多详细信息。

#4


0  

Some of the improvements in organizing projects and design of the layers can be done by focusing on getting the Domain objects correct.

组织项目和层设计的一些改进可以通过专注于使Domain对象正确来完成。

You said you have simple POCO objects as Domain, but the Domain objects should be the one having all the "State and behaviour" of the business. That means you do not need to have BLL and Domain assemblies separate. Once the Domain objects are defined, EF can be used to create the context and entity classes (which are not Domain classes unless there is no additional behaviour compared to your domain object, but still having them different might be good for future requirements).

你说你有简单的POCO对象作为域,但域对象应该是具有业务的所有“状态和行为”的对象。这意味着您不需要将BLL和Domain程序集分开。一旦定义了Domain对象,就可以使用EF创建上下文和实体类(除非与域对象相比没有其他行为,但它们不是域类,但仍然使它们不同可能对将来的要求有利)。

Other minor point is, I think having interfaces distributed within the Domain and Services layer is better in terms of anyone understanding each layer in isolation.

另一个小问题是,我认为在域和服务层中分布的接口在任何人理解每个层时都是更好的。

#1


9  

From a quick glance, I don't think your service and controller/core layer should have the db context injected into them in this manner. They don't actually directly depend on it and doing it in this manner causes some coupling that is not ideal. The core layer should have the user service injected and the user service and BLL should have the repository injected. The repository should have the dbcontext injected by your DI framework and not passed in as a dependency.

从快速浏览一下,我不认为您的服务和控制器/核心层应该以这种方式将db上下文注入其中。它们实际上并不直接依赖它,并且以这种方式进行它会导致一些不理想的耦合。核心层应该注入用户服务,用户服务和BLL应该注入存储库。存储库应该具有由DI框架注入的dbcontext,而不是作为依赖项传入。

#2


4  

Why are you using dependency injection when you are creating 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 are you using so many layers when they actually do nothing? Your example code just shows that using context in controller directly would produce the same result without three wrapper useless layers. It may be just problem of your example but each layer should bring some added logic. If you just use it to call something on lower layer you are most probably overarchitecting your code. This is called onion architecture. That is also a reason why it is not a bad practice to add layer once you need it - not upfront.

顺便说一句。当他们实际上什么都不做的时候你为什么要使用这么多层?您的示例代码只显示直接在控制器中使用上下文将产生相同的结果,而没有三个包装器无用的层。这可能只是你的例子的问题,但每一层都应该带来一些额外的逻辑。如果您只是用它来调用较低层的内容,那么您很可能会对代码进行过多的构建。这被称为洋葱建筑。这也是为什么在需要时添加图层并不是一个不好的做法 - 而不是预先。

#3


1  

Please check this out: http://www.primaryobjects.com/CMS/Article122.aspx EF Repository pattern + Unit Of Work pattern. As for your other layers, it really depends on the application and what it needs to accomplish. Please provide more details on what you're trying to do.

请查看:http://www.primaryobjects.com/CMS/Article122.aspx EF存储库模式+工作单元模式。至于你的其他层,它实际上取决于应用程序以及它需要完成的任务。请提供您正在尝试做的更多详细信息。

#4


0  

Some of the improvements in organizing projects and design of the layers can be done by focusing on getting the Domain objects correct.

组织项目和层设计的一些改进可以通过专注于使Domain对象正确来完成。

You said you have simple POCO objects as Domain, but the Domain objects should be the one having all the "State and behaviour" of the business. That means you do not need to have BLL and Domain assemblies separate. Once the Domain objects are defined, EF can be used to create the context and entity classes (which are not Domain classes unless there is no additional behaviour compared to your domain object, but still having them different might be good for future requirements).

你说你有简单的POCO对象作为域,但域对象应该是具有业务的所有“状态和行为”的对象。这意味着您不需要将BLL和Domain程序集分开。一旦定义了Domain对象,就可以使用EF创建上下文和实体类(除非与域对象相比没有其他行为,但它们不是域类,但仍然使它们不同可能对将来的要求有利)。

Other minor point is, I think having interfaces distributed within the Domain and Services layer is better in terms of anyone understanding each layer in isolation.

另一个小问题是,我认为在域和服务层中分布的接口在任何人理解每个层时都是更好的。

相关文章