Entity framework 使用EF实现通用存储库
对于一个简单的存储库Entity framework 使用EF实现通用存储库,entity-framework,entity-framework-4,repository,repository-pattern,Entity Framework,Entity Framework 4,Repository,Repository Pattern,对于一个简单的存储库 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);
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);
}
现在假设我的存储库实现类如下所示:
public Product Load(Guid rowid)
{
return (from c in _ctx.Products where c.id == rowid select c).FirstOrDefault();
}
public class EntityFrameworkProductsProvider : IRepository<Product> ...
public class EntityFrameworkDefaultProvider<T> : IRepository<T> ...
public class EntityFrameworkDefaultProvider<T> : IRepository<T> where T:class
{
public T Load(Guid rowId)
{
return _context.Set<T>().Find(rowId);
}
}
如果我有几十个或数百个这样的小而简单的实体,当CRUD使用相同的方法实现时,它们都会使用相同的行为,会怎么样?我当然不想去创建一个类来为它们中的每一个实现IRepository
我想要这样的东西:
public Product Load(Guid rowid)
{
return (from c in _ctx.Products where c.id == rowid select c).FirstOrDefault();
}
public class EntityFrameworkProductsProvider : IRepository<Product> ...
public class EntityFrameworkDefaultProvider<T> : IRepository<T> ...
public class EntityFrameworkDefaultProvider<T> : IRepository<T> where T:class
{
public T Load(Guid rowId)
{
return _context.Set<T>().Find(rowId);
}
}
但是我不知道如何实现LINQ Select表达式,因为我当然不能从e in_ctx.t中写入,其中e。。。还是我
我还没有遇到这种情况,因为到目前为止,我只有非常特定的实体具有自定义存储库实现。您可以编写_ctx.Set,而不是编写_ctx.Products。这解决了您需要在存储库中添加一个通用约束(其中T:class)的一半问题
然后,如果rowid是对象的键,则可以使用_ctx.Set.Findrowid而不是LINQ查询来按Id检索
或者,您可以创建一个基接口IHaveId或一个BaseEntity类,无论您喜欢哪个类,它都具有Id属性,然后将其添加为T上的通用约束,这样您就可以在查询中使用它。您可以编写_ctx.Set,而不是编写_ctx.Products。这解决了您需要在存储库中添加一个通用约束(其中T:class)的一半问题
然后,如果rowid是对象的键,则可以使用_ctx.Set.Findrowid而不是LINQ查询来按Id检索
或者,您可以创建一个基接口IHaveId或一个BaseEntity类,无论您喜欢哪个类,它都具有Id属性,然后将其添加为T上的通用约束,这样您就可以在查询中使用它了。我知道这在EF4.1和DbContext API中是可能的,其中,您在上下文中有一个Set方法,该方法获取与类型T对应的实体集。这样,您的存储库可以如下所示:
public Product Load(Guid rowid)
{
return (from c in _ctx.Products where c.id == rowid select c).FirstOrDefault();
}
public class EntityFrameworkProductsProvider : IRepository<Product> ...
public class EntityFrameworkDefaultProvider<T> : IRepository<T> ...
public class EntityFrameworkDefaultProvider<T> : IRepository<T> where T:class
{
public T Load(Guid rowId)
{
return _context.Set<T>().Find(rowId);
}
}
要获取所需的实体,而不是使用来自。。。在里面在我看来,这更清楚:
希望这有助于我知道,在EF4.1中,使用DbContext API可以实现这一点,在该API中,上下文上有一个Set方法,可以获取与T类型对应的实体集。这样,您的存储库可以如下所示:
public Product Load(Guid rowid)
{
return (from c in _ctx.Products where c.id == rowid select c).FirstOrDefault();
}
public class EntityFrameworkProductsProvider : IRepository<Product> ...
public class EntityFrameworkDefaultProvider<T> : IRepository<T> ...
public class EntityFrameworkDefaultProvider<T> : IRepository<T> where T:class
{
public T Load(Guid rowId)
{
return _context.Set<T>().Find(rowId);
}
}
要获取所需的实体,而不是使用来自。。。在里面在我看来,这更清楚:
希望这对您有所帮助,因为您已将问题标记为,并且我假设您正在使用ObjectContext API。ObjectContext提供方法CreateObjectSet,该方法相当于DbContext上的Set 这个问题实际上与以下两个问题重复:
因为您将问题标记为,我假设您使用的是ObjectContext API。ObjectContext提供方法CreateObjectSet,该方法相当于DbContext上的Set 这个问题实际上与以下两个问题重复:
如果您使用的是EF 4.1,请参见此处的示例通用存储库:
如果您使用的是EF 4.1,请参见此处的示例通用存储库:
看看这篇文章:。看看这篇文章:。@Diego Mijelshon:如果id包含的列超过1列怎么办?@Naor:它们不符合他的界面。无论如何,这是一种不好的做法,但是Find支持将对象[]作为参数传递,因此理论上他也可以添加它。@Diego Mijelshon:但是Find方法如何知道如何将每个对象映射到每个键?我问过Ladislav Mrnka,@Naor:按照HasKey方法定义它们的顺序。请参见@Diego Mijelshon:HashKey在哪里定义?@Diego Mijelshon:如果id包含的列超过1列,该怎么办?@Naor:根据他的接口,它们不存在。无论如何,这是一种不好的做法,但是Find支持将对象[]作为参数传递,因此理论上他也可以添加它。@Diego Mijelshon:但是Find方法如何知道如何将每个对象映射到每个键?我问过Ladislav Mrnka,@Naor:按照HasKey方法定义它们的顺序。参见@Diego Mijelshon:HashKey在哪里定义?