对于简单的存储库
public interface ISimpleRepository<T>
{
IApplicationState AppState { get; set; }
void Add(T instance);
void Delete(T instance);
void Delete(Guid rowGuid);
IQueryable<T> GetAll();
T Load(Guid rowGuid);
void SaveChanges();
void Update(T instance);
}
我对类Load()
的特定存储库的Product
方法的实现可能如下所示:
public Product Load(Guid rowid)
{
return (from c in _ctx.Products where c.id == rowid select c).FirstOrDefault();
}
现在假设我的存储库实现类如下所示:
public class EntityFrameworkProductsProvider : IRepository<Product> ...
如果我有几十个或几百个这样的小而简单的实体在做CRUD时会使用相同的行为(使用相同的方法实现)怎么办?我当然不想创建一个类来为每个人实现IRepository。
我想要这样的事情:
public class EntityFrameworkDefaultProvider<T> : IRepository<T> ...
但是我不知道如何实现LINQ Select表达式,因为我当然不能写from e in _ctx.T where e...
或者我?
我还没有碰到这种情况,因为到目前为止我只有非常具体的实体和自定义存储库实现。
答案 0 :(得分:4)
因为您使用entity-framework和entity-framework-4标记了您的问题,我假设您使用的是ObjectContext API。 ObjectContext
提供的方法CreateObjectSet<T>
相当于Set<T>
上的DbContext
。
这个问题实际上是重复的:
答案 1 :(得分:3)
您可以撰写_ctx.Products
,而不是撰写_ctx.Set<T>
。这解决了问题的一半(您需要向存储库添加通用约束where T: class
)
然后,如果rowid是对象的键,则可以使用_ctx.Set<T>.Find(rowid)
而不是LINQ查询来按Id检索。
或者,您可以创建具有IHaveId
属性的基接口BaseEntity
(或任何您喜欢的Id
类),然后将其作为T的通用约束添加,因此您可以在查询中使用它。
答案 2 :(得分:2)
如果您使用的是EF 4.1,请在此处查看示例通用存储库: http://www.asp.net/entity-framework/tutorials/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
答案 3 :(得分:1)
我知道在使用DbContext API的EF4.1中可以实现这一点,在上下文中你有一个“Set”方法,它可以获得与类型T对应的实体集。这样,你可以让你的存储库像这样:
public class EntityFrameworkDefaultProvider<T> : IRepository<T> where T:class
{
public T Load(Guid rowId)
{
return _context.Set<T>().Find(rowId);
}
}
还有一句话:我认为你可以使用这种语法:
return _ctx.Products.FirstOrDefault(c=>c.id == rowid);
获取您想要的实体而不是使用(from ... in ...)。它更清楚(在我看来):))
希望这有帮助