【发布时间】:2017-08-07 10:45:53
【问题描述】:
我想使用实体框架实现一个通用的存储库模式(我知道关于存储库有很多有争议的观点,但这仍然是我需要的)。 我想要的界面如下:
public interface IRepository
{
IQueryable<TEntity> Query<TEntity>()
where TEntity: Entity;
void Save<TEntity>(TEntity entity)
where TEntity : Entity;
void Delete<TEntity>(TEntity entity)
where TEntity : Entity;
}
Entity 是一个只有int ID 属性的基类。
并像这样使用它:
IRepository repository = ... // get repository (connects to DB)
int userId = GetCurrentUserId();
if (!repository.Query<User>().Any(u => u.Id == userId)) // performs SELECT query
{ /*return error*/ }
var newOrder = new Order { UserId = userId, Status = "New" }
repository.Save(newOrder); // performs INSERT query
...
newOrder.Status = "Completed";
repository.Save(newOrder); // performs UPDATE query
我想避免UnitOwWork,只要调用Save() 或Delete() 就将所有对象更改提交到数据库。我想做的事情看起来很简单,但我没有找到任何使用 EntityFramework 的示例。我能找到的最接近的示例是 this answer,但它使用 UnitOwWork 和 repository-per-entity,其中比我需要做的更复杂。
【问题讨论】:
-
如果你想保持简单,那么不要在实体框架中使用存储库模式。实体框架本身已经是一个存储库模式,您只是在现有抽象之上添加更多抽象,它没有任何好处。相反,它可能会使您的代码更难维护和使用,同时增加开发额外不必要层的成本。
-
这不是一个通用存储库,它只是一个 DbContext 的包装器。我很好奇您是如何实现
Save的,因为它表明您可以有选择地保存一个实体,即使上下文包含更多已更改的实体。难以置信。如果可以的话,这违背了SaveChanges方法的目的。 -
@GertArnold,接口是一个存储库。我已经使用纯 ADO.NET 和 Dapper 实现了其中的一部分。 (顺便说一句,这是我想要对 EF 进行抽象的原因之一:我的应用程序的某些部分包含 EF 不完全支持的复杂查询,但我希望使用一个抽象来执行所有查询:IRepository)IRepository 不知道或关心 EF 或 DbContext。它应该是所有数据操作的通用简单接口(这在后台可能非常复杂 - 就像为不同的实体类型使用不同的 ORM)。
-
@Nazz IQueryable
将使用带有实现(f.i. EF)的 IRepository 接口“感染”您的代码。它不再那么抽象了 -
@Nazz 所以你是说在你的存储库抽象背后你可以有 EF 或 Dapper?
标签: c# entity-framework repository-pattern