代码优先 - 存储库模式 - 设计考虑因素

时间:2016-03-02 04:53:41

标签: c# entity-framework architecture repository-pattern unit-of-work

我正在尝试创建一个Repository + UnitOfWork平台。我的IRepository界面如下所示。

 public interface IRepository<TEntity>
        where TEntity : IEntity
    {
        IQueryable<TEntity> GetAll();
        TEntity Get(int id);
        IQueryable<TEntity> FindBy(Expression<Func<TEntity, bool>> predicate);
        TEntity Add(TEntity entity);
        TEntity Delete(TEntity entity);
        void Save(TEntity entity);
    }

我对以下一些问题感到困惑......

  1. 在界面中处理的IEntity是代码优先实体(不是业务对象)。理想情况下,存储库是否应该处理(接受+返回)它们或业务对象本身?
  2. Repository应该返回IQueryable还是IEnumerable?
  3. 如果问题#1的答案是业务对象,那么如何 实现实体和业务对象之间的映射?
  4. 如果我引入一个新的服务层(将是 由客户端使用),服务层将是调用Repository方法和映射的一次。这是对的吗?
  5. 如果上述问题的答案是肯定的,那么进行映射 服务层打破单一责任原则。如何获得 结束了吗?
  6. 我也欢迎实现Repository和UnitOfWork的示例应用程序(MVC,EF,SQL Server)的链接。

2 个答案:

答案 0 :(得分:1)

软件设计没有对错,但据我所知,有一些设计实践可以回答你的问题。

  

在接口中处理的IEntity是代码优先实体   (不是业务对象)。理想情况下是预期要处理的存储库   (接受+返回)他们或业务对象本身?

  • 理想情况下,存储库层应该只处理实体对象。不要将它与业务对象混合在一起。映射逻辑
  

Repository应该返回IQueryable还是IEnumerable?

  • 我更愿意使用Iqueryable,因为Iqueryable也继承自IEnumerable,所以IEnumerable可以做的每一件事,IQueryable都可以做。更重要的是,Iqueryable的每个查询尝试都将在database层执行。总而言之,如果您不确定是否仍需要执行任何额外查询(例如:过滤数据),则IQueryable绝对是必须的。
  

如果问题#1的答案是业务对象,那么如何   实现实体和业务对象之间的映射?

  • 有许多方法可以进行映射,AutoMapper是一个很好的稳定库。
  

如果我引入一个新的服务层(将由它使用)   客户端),服务层将是调用存储库的一次   方法和映射。这是对的吗?

  • 这实际取决于您设计服务层的方式。通常的流程是:

    致电Repository个方法=&gt; get data =&gt;映射到业务对象=&gt;执行额外的逻辑=&gt;返回业务对象

  

如果上述问题的答案是肯定的,那么进行映射   服务层打破单一责任原则。如何克服   它?

如单一责任原则的定义(一个类应该只有一个改变的理由),您的服务层责任是对业务对象执行额外的逻辑,所以我会说它会失败不违反SRP。

public SampleDTO SampleServiceMethod(InputModel input)
{
    var model = _sampleRepository.FindBy(input.Id);

    var dto = SampleMapper.ToSampleDto(model);

    // do something and return the dto
    dto.Test = 1;

    return dto;
}

答案 1 :(得分:1)

  
      
  1. 在界面中处理的IEntity是代码优先实体(不是业务对象)。理想情况下,存储库是否应该处理(接受+返回)它们或业务对象本身?
  2.   

您是否有任何理由拥有单独的域模型(业务对象)和持久性模型(代码优先实体)? EF对代码优先类没有很多额外的要求,通常你可以直接保留业务对象。

如果您选择具有单独的持久性模型,那么它应该是存储库的实现细节。存储库应该与业务对象一起使用。

  
      
  1. Repository应该返回IQueryable还是IEnumerable?
  2.   

这取决于。 IQueryable使您可以轻松地在应用程序层中创建查询而无需修改存储库。当你有一个单独的简单读取堆栈时,它在CQRS中特别有用。

您必须知道使用IQueryable会引入对基础数据源的依赖。更改数据源时,在运行时可能会失败使用一个数据源的查询。

  
      
  1. 如果问题#1的答案是业务对象,那么如何实现实体和业务对象之间的映射?
  2.   

您可以使用Automapper等工具。

  
      
  1. 如果我引入一个新的服务层(将由客户端使用),服务层将是调用Repository方法和映射的一次。这是对的吗?
  2.   

服务层将调用存储库。存储库将返回/添加/修改业务对象。任何映射(如有必要)都将在存储库中完成。