具有服务层、业务层和实体框架的N层体系结构



我只是想得到一些关于我构建应用程序的反馈/帮助。我目前的解决方案结构如下:

  • UI(实际MVC应用程序)
  • Core(仅控制器和视图模型)
  • 服务
  • BLL
  • 数据(实体框架DbContext,映射到域对象)
  • 域(简单POCO对象)
  • 接口

其他东西

  • Ninject将DbContext注入控制器(每个请求)
  • 将域对象映射到ViewModel的AutoMapper

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

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

我提供了一些代码如下:

控制器的一个例子如下:

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类:

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

最后,业务层类:

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

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

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

当您直接在服务中创建依赖项时,为什么要使用依赖项注入?

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

Btw。为什么你使用这么多层,而它们实际上什么都不做?您的示例代码只是表明,在没有三个无用的包装层的情况下,直接在控制器中使用上下文将产生相同的结果。这可能只是示例的问题,但每一层都应该添加一些逻辑。如果您只是使用它来调用较低层上的某个东西,那么您很可能对代码进行了过度的体系结构保护。这就是所谓的洋葱建筑。这也是为什么一旦你需要添加图层(而不是提前添加)并不是一个坏做法的原因。

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

在组织项目和层设计方面的一些改进可以通过关注Domain对象的正确性来完成。

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

另一个次要的问题是,我认为在域和服务层中分布接口会更好地让任何人孤立地理解每一层。

最新更新