vie*_*uoc 7 c# entity-framework repository-pattern
我计划将数据访问层迁移到使用存储库模式和工作单元.
我知道存储库将帮助我轻松地将持久性存储(数据库,集合等)和EF等技术更改为MongoDB.所以我注意到了一些存储库实现的关键点,例如:
IEnumerable
而不是IQueryable
如果我在项目中的实现存储库中应用这些关键点,我完全忘记了如何处理与多个实体相关的复杂查询.
目前,我已经有了是对BLL库有很多服务类将直接联系到DbContext
与DbSet
EF和一些像这样的验证:
public IEnumerable<ProjectDTO> GetProjectWithDetails()
{
// Validation
// Logging
// Can be any logic need to before query data.
Dbcontext.Projects.Where(p =>
// multiple of conditions go here follow business rules
// conditions will need to check another entities (task, phase, employee...) such as:
// 1. project have task status 'in-progress' .. etc
// 2. project have employeeid 1,2,3..
// 3. project have stask start at some specific date.
// 4....
)
.Select(p => new ProjectDTO
{
Label = p.Label,
Phase = new PhaseDTO{
Label = p.Phase.Label,
Tasks = p.Phase.Tasks.Select(t => new TaskDTO{
// some related properties
})
}
}).ToList();
}
Run Code Online (Sandbox Code Playgroud)
我目前正在使用数据传输对象(DTO)作为控制器上的模型和视图模型之间的中间类,并使用Mapper映射属性.
如果我在上面的存储库上保留关键注释,我需要多次往返数据库获取数据,它将返回整个模型而不是有用的列.但是,如果我将这些方法迁移到存储库,我将破坏存储库模式,因为它将包含业务逻辑和返回类型而不是模型.
所以问题是在这种情况下我应该怎么做?请给我一些建议让我走上正轨.
非常感谢.
这取决于意见和用例,但是我个人不同意您提到的一些关键点。
返回IEnumerable而不是IQueryable
同意。返回会IQueryable
破坏存储库存在的基本目的。网上有很多文章解释了这如何带来比解决方案更多的问题。虽然,我学会了永不言败。请参考这个,这个或这个。或者直接搜索google。
存储库应仅负责CRUD操作
同意。使用简单的CRUD,它也可以执行复杂的读取和写入操作。我的经验表明,在特殊情况下,如果要在RDBMS端实现它,则必须将业务逻辑的一部分放入存储库中。这不是对还是错。如果您知道自己在做什么,那应该没有问题。
存储库方法的返回类型应为模型(实体)
如果您不使用DDD,则可以。否则,是实施决定。对于像EF或NHibernate这样的完整ORM,最好直接返回域模型,而不是按表实体实例返回。
始终建议存储库应返回域模型。这样,从RDBMS返回的数据与域模型的映射(反之亦然)成为存储库的责任。这避免了将持久性问题泄漏到存储库外部的必要性,从而使其余的应用程序持久性变得无知。
但是,并非每个应用程序都实现DDD。许多小型应用程序设计实体将它们与数据库设计一对一映射。在这种情况下,存储库可能会返回实体(等效于您的表和字段)本身,并且映射成为调用代码的责任。或者,存储库可以映射必要的模型并返回模型本身。强烈建议不要这样做,因为存在上述问题。这样,您就必须放弃完整的ORM提供的某些功能。
这一切都取决于您的问题,您的设计目标,应用程序的大小以及所实现的其他设计模式等。这就是为什么它成为设计决策。
仅实现聚合根的存储库
同意是否与DDD一起使用。如果没有,则像每个表存储库一样有多个选择。同样,取决于用例。
关于复杂查询
存储库不必仅实现简单的CRUD方法。它还可能返回复杂的对象图。它可能会执行复杂的查询。这就是说,用简单的方法,如Get
,GetById
等,它也可能会消耗喜欢复杂的方法GetTopBrokenVehicles(vehicleType, top)
。如果您为复杂的查询编写单独的方法,那绝对没问题。
挑战在于,如何接受必要的参数。您可以内联接受参数,也可以构建单独的简单输入参数类。
这是Repository和UoW的示例代码。
归档时间: |
|
查看次数: |
2043 次 |
最近记录: |