具有 EntityFramework 的通用存储库
Posted
技术标签:
【中文标题】具有 EntityFramework 的通用存储库【英文标题】:Generic Repository with EntityFramework 【发布时间】: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 IQueryable1-创建一个接口
interface IMain<T> where T : class
List<T> GetAll();
T GetById(int id);
void Add(T entity);
void Edit(T entity);
void Del(int id);
int Savechange();
2-创建一个类
public class Main<T> : IMain<T> where T : class
public DataContext db;
public void Add(T entity)
db.Set<T>().Add(entity);
public void Del(int id)
var q = GetById(id);
db.Set<T>().Remove(q);
public void Edit(T entity)
db.Entry<T>(entity).State = EntityState.Modified;
public List<T> GetAll()
return db.Set<T>().Select(a=>a).ToList();
public T GetById(int id)
return db.Set<T>().Find(id);
public int Savechange()
return db.SaveChanges();
3-创建一个名为 YourTable ForExample Student
的存储库 public class Student : Main<Tbl_Student>
public Student()
db = new DataContext();
4-为您的行动编写此代码
Student student=new Student();
student.Del(3);
int a = student.Savechange();
【讨论】:
【参考方案2】:您可以使用表达式关键字来做到这一点;
public interface IRepository<TEntity> where TEntity : Entity
IQueryable<TEntity> Query(Expression<Func<TEntity, bool>> predicate);
void Save(TEntity entity);
void Delete(TEntity entity);
public abstract class EfRepository<T> : IRepository<T> where T : Entity
private readonly DbContext _dbContext;
protected readonly DbSet<T> _dbSet;
public EfRepository(YourDbContextContext dbContext)
_dbContext = dbContext;
_dbSet = dbContext.Set<T>();
public void Delete(T entity)
if (entity == null) return;
else
DbEntityEntry dbEntityEntry = _dbContext.Entry(entity);
if (dbEntityEntry.State != EntityState.Deleted)
dbEntityEntry.State = EntityState.Deleted;
else
_dbSet.Attach(entity);
_dbSet.Remove(entity);
_dbContext.SaveChanges();
public IQueryable<T> Query(Expression<Func<T, bool>> predicate)
return _dbSet.Where(predicate);
public void Save(T entity)
if (entity.Id > 0)
_dbSet.Attach(entity);
_dbContext.Entry(entity).State = EntityState.Modified;
_dbContext.SaveChanges();
else
_dbSet.Add(entity);
_dbContext.SaveChanges();
public class Entity
public int Id get; set;
然后创建您的存储库;
public interface IUserRepository : IRepository<User>
//Also you can add here another methods according to your needs
public class UserRepository : EfRepository<User>,IUserRepository
public UserRepository(YourDbContext yourDbContext) : base(yourDbContext)
那就用吧;
IUserRepository _userRepository => Getit
//If there are entities according to your conditions, this will return them, then use it
_userRepository.Query(u => u.Id == userId);
【讨论】:
【参考方案3】:我曾经使用它,但正如许多开发人员所说,它会增加代码的复杂性并可能导致问题:
我的interface IRepositoryBase
的代码:
public interface IRepositoryBase<TEntity> where TEntity : class
void Add(TEntity objModel);
void AddRange(IEnumerable<TEntity> objModel);
TEntity GetId(int id);
Task<TEntity> GetIdAsync(int id);
TEntity Get(Expression<Func<TEntity, bool>> predicate);
Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> predicate);
IEnumerable<TEntity> GetList(Expression<Func<TEntity, bool>> predicate);
Task<IEnumerable<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate);
IEnumerable<TEntity> GetAll();
Task<IEnumerable<TEntity>> GetAllAsync();
int Count();
Task<int> CountAsync();
void Update(TEntity objModel);
void Remove(TEntity objModel);
void Dispose();
我的interface
在repsoitory RepositoryBase
上的实现代码:
public class RepositoryBase<TEntity> : IRepositoryBase<TEntity> where TEntity : class
#region Fields
protected readonly EntityContext _context = new EntityContext();
#endregion
#region Methods
public void Add(TEntity objModel)
_context.Set<TEntity>().Add(objModel);
_context.SaveChanges();
public void AddRange(IEnumerable<TEntity> objModel)
_context.Set<TEntity>().AddRange(objModel);
_context.SaveChanges();
public TEntity GetId(int id)
return _context.Set<TEntity>().Find(id);
public async Task<TEntity> GetIdAsync(int id)
return await _context.Set<TEntity>().FindAsync(id);
public TEntity Get(Expression<Func<TEntity, bool>> predicate)
return _context.Set<TEntity>().FirstOrDefault(predicate);
public async Task<TEntity> GetAsync(Expression<Func<TEntity, bool>> predicate)
return await _context.Set<TEntity>().FirstOrDefaultAsync(predicate);
public IEnumerable<TEntity> GetList(Expression<Func<TEntity, bool>> predicate)
return _context.Set<TEntity>().Where<TEntity>(predicate).ToList();
public async Task<IEnumerable<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate)
return await Task.Run(() =>
_context.Set<TEntity>().Where<TEntity>(predicate));
public IEnumerable<TEntity> GetAll()
return _context.Set<TEntity>().ToList();
public async Task<IEnumerable<TEntity>> GetAllAsync()
return await Task.Run(() => _context.Set<TEntity>());
public int Count()
return _context.Set<TEntity>().Count();
public async Task<int> CountAsync()
return await _context.Set<TEntity>().CountAsync();
public void Update(TEntity objModel)
_context.Entry(objModel).State = EntityState.Modified;
_context.SaveChanges();
public void Remove(TEntity objModel)
_context.Set<TEntity>().Remove(objModel);
_context.SaveChanges();
public void Dispose()
_context.Dispose();
#endregion
我的实体interface
:
public interface IMyEntityRepository : IRepositoryBase<MyEntity>
//here you can place other implementations your repository doesn't have
public class MyEntityRepository : RepositoryBase<MyEntity>, IMyEntityRepository
如何调用(我用的是依赖注入):
public class MyServiceOrController
#region Fields
private readonly IMyEntityRepository _myEntityRepository;
#endregion
#region Constructors
public MyServiceOrController(IMyEntityRepository myEntityRepository)
_myEntityRepository = myEntityRepository;
#endregion
#region Methods
public IList<MyEntity> TestGetAll()
return _myEntityRepository.GetAll();
#endregion
【讨论】:
以上是关于具有 EntityFramework 的通用存储库的主要内容,如果未能解决你的问题,请参考以下文章
Entity Framework 6 异步操作和 TranscationScope