洋葱架构 - 服务层责任

Usm*_*lid 4 asp.net-mvc design-patterns repository-pattern onion-architecture

我正在学习Jeffrey Palermo的Onion Architecture两周多了.我按照本教程创建了一个测试项目.在学习期间,我在SO上遇到了这个问题.根据公认的答案,有人nwang建议像GetProductsByCategoryId这样的方法不应该在Repository中,而另一方面则Dennis Traub 建议它是Repository的责任.我在做的是:

我有一个通用存储库Domain.Interface,我有一个方法Find:

public interface IRepository<TEntity> where TEntity : class
{
     IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> filter = null);
     .......
     .......
     .......
}
Run Code Online (Sandbox Code Playgroud)

然后,我创建了一个BaseRepositoryInfrastucture.Data:

public class RepositoryBase<TEntity> : IRepository<TEntity> where TEntity : class
{
     internal readonly DbSet<TEntity> dbSet;
     public virtual IEnumerable<TEntity> Find(
            Expression<Func<TEntity, bool>> filter = null)
     {
            IQueryable<TEntity> query = dbSet;

            if (filter != null)
            {
                query = query.Where(filter);
            }
            return query.ToList();
     }
}
Run Code Online (Sandbox Code Playgroud)

我有一个具体的存储库Infrastructure.Data

public class ProductRepository : RepositoryBase<Product>, IProductRepository
{
      public ProductRepository(MyDBContext context)
           : base(context)
       {         

       }
}
Run Code Online (Sandbox Code Playgroud)

现在,我在服务层中所做的是将存储库注入服务并调用Repository.Find类似的方法GetProductsByCategoryId.喜欢 :

public class ProductService : IProductService
{
     private readonly IUnitOfWork _unitOfWork;
     private readonly IProductRepository _productRepository;

     public ProductService(IUnitOfWork unitOfWork, IProductRepository productRepository)
     {
          _unitOfWork = unitOfWork;
          _productRepository = productRepository;
     }

     public IList<Product> GetProductsByCategoryId(int CategoryId)
     {
          // At the moment, My code is like this:
          return _productRepository.Find(e => e.CategoryId == CategoryId).ToList();

          // My confusion is here. Am I doing it right or I need to take this code to 
          // ProductRepository and call _productRepositoy.GetProductsByCategoryId(CategoryId) here instead.
          // If I do this, then Service Layer will become more of a wrapper around repository. Isn't it?
          // My question is : What exactly will be the responsibility of the Service Layer in Onion Architecture?
         }
    }
Run Code Online (Sandbox Code Playgroud)

Max*_*xSC 6

您设计应用程序的方式是可以的......但前提是您的服务将处理其他事情,而不仅仅是整理存储库方法!

始终牢记YAGNI原则:

当你真正需要它们时,总是要实现它们,永远不要只是预见到你需要它们

假设您有一个用户故事,说无论何时在您的数据库中找不到产品描述,您都应该从其他地方(调用外部服务或其他东西)进行检索.然后很明显你的ProductService必须有一个

private readonly IProductRepository _productRepository;
Run Code Online (Sandbox Code Playgroud)

还有一个

private readonly IProductDescriptionService _productDescriptionService;
Run Code Online (Sandbox Code Playgroud)

在这种情况下,在存储库之上添加服务层确实很有意义.

  • 好.我在SO上制作了一堆[洋葱相关答案](http://stackoverflow.com/search?q=user:1660523+ [洋葱 - 建筑]).您可能会发现其中一些很有趣. (2认同)

Col*_*con 5

我发现,有时为了它而事物可能会被抽象,并且没有任何实际价值.我会说你的例子中的结构很好,并且正确地遵循了模式.正确地说,您的服务层用于满足客户端UI的需求,它与数据层松散耦合,并包含操作数据所需的任何业务逻辑.

我总是认为开始简单并以你的结构为基础比过度抽象,过于复杂和过度膨胀项目更有成效.业务或技术案例通常会推动项目,并决定是否需要.