我正在尝试创建一个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);
}
我对以下一些问题感到困惑......
我也欢迎实现Repository和UnitOfWork的示例应用程序(MVC,EF,SQL Server)的链接。
答案 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)
- 在界面中处理的IEntity是代码优先实体(不是业务对象)。理想情况下,存储库是否应该处理(接受+返回)它们或业务对象本身?
醇>
您是否有任何理由拥有单独的域模型(业务对象)和持久性模型(代码优先实体)? EF对代码优先类没有很多额外的要求,通常你可以直接保留业务对象。
如果您选择具有单独的持久性模型,那么它应该是存储库的实现细节。存储库应该与业务对象一起使用。
- Repository应该返回IQueryable还是IEnumerable?
醇>
这取决于。 IQueryable
使您可以轻松地在应用程序层中创建查询而无需修改存储库。当你有一个单独的简单读取堆栈时,它在CQRS中特别有用。
您必须知道使用IQueryable
会引入对基础数据源的依赖。更改数据源时,在运行时可能会失败使用一个数据源的查询。
- 如果问题#1的答案是业务对象,那么如何实现实体和业务对象之间的映射?
醇>
您可以使用Automapper等工具。
- 如果我引入一个新的服务层(将由客户端使用),服务层将是调用Repository方法和映射的一次。这是对的吗?
醇>
服务层将调用存储库。存储库将返回/添加/修改业务对象。任何映射(如有必要)都将在存储库中完成。