【问题标题】:Generic Repository with EntityFramework具有 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 IQueryable 将使用带有实现(f.i. EF)的 IRepository 接口“感染”您的代码。它不再那么抽象了
  • @Nazz 所以你是说在你的存储库抽象背后你可以有 EF 或 Dapper?

标签: c# entity-framework repository-pattern


【解决方案1】:

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 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
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-06-22
        • 1970-01-01
        • 2021-07-23
        • 1970-01-01
        • 1970-01-01
        • 2015-06-05
        • 2021-04-12
        • 2013-05-10
        相关资源
        最近更新 更多