Универсальный репозиторий с EntityFramework

Я хотел бы реализовать общий шаблон репозитория с использованием 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 и хранилище для каждой сущности, что сложнее, чем то, что мне нужно сделать.

0 ответов

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-To Your Action Написать этот код

Student student=new Student();
student.Del(3);
int a = student.Savechange();

Я использовал его, но, как говорили многие разработчики, это усложнит ваш код и может вызвать проблемы:

Код для моего 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 в хранилище 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
}

Вы можете сделать это с помощью ключевого слова expression;

    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);
Другие вопросы по тегам