使用EntityFramework的通用存储库

8

我希望使用Entity Framework实现通用存储库模式(我知道关于存储库有许多争议,但这仍然是我需要的)。 我希望它具有以下接口:

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完成它的示例。最接近的示例是这个答案,但它使用UnitOwWork和每个实体的存储库,比我需要做的更加复杂。

3
如果你想保持简单,就不要在Entity Framework中使用仓储模式。Entity Framework本身已经是一个仓储模式,你只是在现有的抽象层之上添加更多的抽象层,这没有任何好处。相反,它可能会使你的代码更难维护和使用,同时增加开发额外不必要的层的成本。 - Igor
@AlessandroD'Andria,我的意思是我可以使用Dapper进行一些查询(例如:如果(Entity is XXX)QueryWithDapper() else if(Entity is YYY)QueryWithNHibernate() else QueryWithEf())。显然,Dapper不能作为此接口的完整实现,因为它不支持“IQueryable”。 - Nazz
@Nazz,在这种情况下,我会继续使用提供给我最小公分母的技术,即Dapper。 - Alessandro D'Andria
好吧,称其为存储库(这本身就有争议)。它不是一个通用存储库。您可以通过一个存储库实例操纵任何类型。它只是一个具有通用方法的类,这使得它的功能非常不清楚。如果您使用同一实例执行Delete(order)Save(customer),我不清楚会发生什么。我不喜欢这种模糊性。 - Gert Arnold
@GertArnold,我不确定我理解什么是不清楚的。如果你执行Delete(order); Save(customer),你应该得到两个查询:DELETE FROM Orders WHERE Id=x,UPDATE Customers SET ... WHERE Id=x; 如果任何查询失败(即DELETE返回0行),存储库应该抛出异常并且不回滚任何先前的更新。 - Nazz
显示剩余6条评论
3个回答

3

1-创建一个接口

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的存储库,例如学生

 public class Student : Main<Tbl_Student>
    {
        public Student()
        {
            db = new DataContext();
        }
    }

第四步,编写以下代码

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);

0

我曾经使用过它,但像许多开发人员所说的那样,它会增加代码的复杂性并可能导致问题:

我的 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(); 
}

实现我的接口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
}

我的实体 接口

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
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接