0

我正在尝试构建一个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. 储存库应该返回IQueryable还是IEnumerable?
  3. 如果问题#1的答案是业务对象,那么如何 实现实体和业务对象之间的映射?
  4. 如果我引入一个新的服务层(将由客户端使用 ),服务层将是调用Repository方法和映射的一次。它是否正确?
  5. 如果对上述问题的回答是肯定的,那么在 服务层进行映射会破坏单一责任原则。如何获得 ?

我也欢迎一个示例应用程序(MVC,EF,SQL Server)的链接,其中实现了Repository和UnitOfWork。

回答

1

软件设计没有正确或错误,但在我的知识范围内,有一些设计实践可以回答你的问题。

在界面中处理的IEntity是代码优先实体 (不是业务对象)。理想情况下,预计将处理 (接受+返回)它们或业务对象本身?

  • 理想情况下,存储库层只能处理实体对象。不要淹没它的业务对象&映射逻辑

如若存储库返回的IQueryable或IEnumerable的?

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

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

  • 是有很多做映射的方式,AutoMapper是实现这一目的的良好和稳定的图书馆。

如果我介绍一个新的服务层(这将是由客户端 被消耗),服务层将是它调用库 方法和映射一次。它是否正确?

  • 这真的取决于你如何设计你的服务层。通常的流程是:

    呼叫Repository方法=>获取数据=>映射到业务对象=>执行额外的逻辑=>回报的业务对象

如果回答上述问题是肯定的,然后在 服务层做映射违反单一责任原则。如何获得 呢?

在单一责任的定义原则(类应该只有一个理由去改变),你的服务层责任心是对业务对象执行额外的逻辑,所以我会说这woult不违反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. 的IEntity这是在接口处理的代码第一实体(未业务对象)。理想情况下,仓库是否可以处理(接受+返回)它们或业务对象本身?

你有任何理由有单独的域模型(业务对象)和持久性模型(代号第一实体)? EF对代码优先级没有太多额外要求,通常您可以直接持久存储业务对象。

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

  1. Repository是否应返回IQueryable或IEnumerable?

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

您必须注意,使用IQueryable引入了对底层数据源的依赖关系。当您更改数据源时,运行一个数据源的查询可能会在运行时失败。

  • 如果对问题1回答是业务对象,那么如何实现实体和业务对象之间的映射?
  • 您可以使用类似Automapper的工具。

  • 如果我介绍一个新的服务层(其将被客户端被消耗),服务层将是它调用库方法,以及映射一次。它是否正确?
  • 服务层将调用存储库。存储库将返回/添加/修改业务对象。任何映射(如有必要)都将在存储库中完成。

    相关问题