有没有人有一个非常完整的EF 6.1示例通用存储库?

 qzq9037091 发布于 2023-01-29 10:49

我有自己的存储库,如下所示.但是,这并未考虑一些新功能,例如范围功能.有没有人有一个包含所有内容的存储库.我在网上搜索过这个,但是我找不到最新的东西.这就是我所拥有的.我希望有更多的东西,并提供许多方法的IQueryable:

namespace Services.Repositories
{
    /// 
    /// The EF-dependent, generic repository for data access
    /// 
    /// Type of entity for this Repository.
    public class GenericRepository : IRepository where T : class
    {
        public GenericRepository(DbContext dbContext)
        {
            if (dbContext == null) 
                throw new ArgumentNullException("An instance of DbContext is required to use this repository", "context");
            DbContext = dbContext;
            DbSet = DbContext.Set();
        }

        protected DbContext DbContext { get; set; }

        protected DbSet DbSet { get; set; }

        public virtual IQueryable Find(Expression> predicate)
        {
            return DbSet.Where(predicate);
        }

        public virtual IQueryable GetAll()
        {
            return DbSet;
        }

        public virtual T GetById(int id)
        {
            //return DbSet.FirstOrDefault(PredicateBuilder.GetByIdPredicate(id));
            return DbSet.Find(id);
        }

        public virtual void Add(T entity)
        {
            DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
            if (dbEntityEntry.State != EntityState.Detached)
            {
                dbEntityEntry.State = EntityState.Added;
            }
            else
            {
                DbSet.Add(entity);
            }
        }

        public virtual void Update(T entity)
        {
            DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
            if (dbEntityEntry.State == EntityState.Detached)
            {
                DbSet.Attach(entity);
            }  
            dbEntityEntry.State = EntityState.Modified;
        }

        public virtual void Delete(T entity)
        {
            DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
            if (dbEntityEntry.State != EntityState.Deleted)
            {
                dbEntityEntry.State = EntityState.Deleted;
            }
            else
            {
                DbSet.Attach(entity);
                DbSet.Remove(entity);
            }
        }

        public virtual void Delete(int id)
        {
            var entity = GetById(id);
            if (entity == null) return; // not found; assume already deleted.
            Delete(entity);
        }
    }
}

Colin.. 14

您可以添加以下新功能:

public virtual void AddRange(IEnumerable entities)
{
    DbContext.Set().AddRange(entities);
}

public virtual void RemoveRange(IEnumerable entities)
{
    DbContext.Set().RemoveRange(entities);
}


danludwig.. 10

您不需要通用存储库.DbContext已经一个通用的存储库.试试这个:

public class EntityDbContext : DbContext, IWriteEntities
{
    public IQueryable EagerLoad(IQueryable query,
        Expression> expression)
    {
        // Include will eager load data into the query
        if (query != null && expression != null)
            query = query.Include(expression);
        return query;
    }

    public IQueryable Query()
    {
        // AsNoTracking returns entities that are not attached to the DbContext
        return Set().AsNoTracking();
    }

    public TEntity Get(object firstKeyValue, params object[] otherKeyValues)
    {
        if (firstKeyValue == null) throw new ArgumentNullException("firstKeyValue");
        var keyValues = new List { firstKeyValue };
        if (otherKeyValues != null) keyValues.AddRange(otherKeyValues);
        return Set().Find(keyValues.ToArray());
    }

    public Task GetAsync(object firstKeyValue, params object[] otherKeyValues)
    {
        if (firstKeyValue == null) throw new ArgumentNullException("firstKeyValue");
        var keyValues = new List { firstKeyValue };
        if (otherKeyValues != null) keyValues.AddRange(otherKeyValues);
        return Set().FindAsync(keyValues.ToArray());
    }

    public IQueryable Get()
    {
        return Set();
    }

    public void Create(TEntity entity)
    {
        if (Entry(entity).State == EntityState.Detached)
            Set().Add(entity);
    }

    public void Update(TEntity entity)
    {
        var entry = Entry(entity);
        entry.State = EntityState.Modified;
    }

    public void Delete(TEntity entity)
    {
        if (Entry(entity).State != EntityState.Deleted)
            Set().Remove(entity);
    }

    public void Reload(TEntity entity)
    {
        Entry(entity).Reload();
    }

    public Task ReloadAsync(TEntity entity)
    {
        return Entry(entity).ReloadAsync();
    }

    public void DiscardChanges()
    {
        foreach (var entry in ChangeTracker.Entries().Where(x => x != null))
        {
            switch (entry.State)
            {
                case EntityState.Added:
                    entry.State = EntityState.Detached;
                    break;
                case EntityState.Modified:
                    entry.State = EntityState.Unchanged;
                    break;
                case EntityState.Deleted:
                    entry.Reload();
                    break;
            }
        }
    }

    public Task DiscardChangesAsync()
    {
        var reloadTasks = new List();
        foreach (var entry in ChangeTracker.Entries().Where(x => x != null))
        {
            switch (entry.State)
            {
                case EntityState.Added:
                    entry.State = EntityState.Detached;
                    break;
                case EntityState.Modified:
                    entry.State = EntityState.Unchanged;
                    break;
                case EntityState.Deleted:
                    reloadTasks.Add(entry.ReloadAsync());
                    break;
            }
        }
        return Task.WhenAll(reloadTasks);
    }
}


...如果您需要将UoW与命令中的查询分开,那么接口只是一种形式:

public interface IUnitOfWork
{
    int SaveChanges();
    Task SaveChangesAsync();
    Task DiscardChangesAsync();
    void DiscardChanges();
}

public interface IReadEntities
{
    IQueryable Query();

    IQueryable EagerLoad(IQueryable query, 
        Expression> expression);
}

public interface IWriteEntities : IUnitOfWork, IReadEntities
{
    TEntity Get(object firstKeyValue, params object[] otherKeyValues);
    Task GetAsync(object firstKeyValue,
        params object[] otherKeyValues);
    IQueryable Get();
    void Create(TEntity entity);
    void Delete(TEntity entity);
    void Update(TEntity entity);
    void Reload(TEntity entity);
    Task ReloadAsync(TEntity entity);
}

有了这个,您的接口不需要是通用的,因为这些方法是通用的.

private readonly IWriteEntities _entities;
...
_entities.Get(keyA);
await _entities.GetAsync(keyB);
_entities.Get.Where(...
var results = await _entities.Query().SingleOrDefaultAsync(...

您刚刚在上面的代码中保存了3个不必要的通用存储库依赖项.一个界面可以处理所有4种权利类型.

2 个回答
  • 您不需要通用存储库.DbContext已经一个通用的存储库.试试这个:

    public class EntityDbContext : DbContext, IWriteEntities
    {
        public IQueryable<TEntity> EagerLoad<TEntity>(IQueryable<TEntity> query,
            Expression<Func<TEntity, object>> expression)
        {
            // Include will eager load data into the query
            if (query != null && expression != null)
                query = query.Include(expression);
            return query;
        }
    
        public IQueryable<TEntity> Query<TEntity>()
        {
            // AsNoTracking returns entities that are not attached to the DbContext
            return Set<TEntity>().AsNoTracking();
        }
    
        public TEntity Get<TEntity>(object firstKeyValue, params object[] otherKeyValues)
        {
            if (firstKeyValue == null) throw new ArgumentNullException("firstKeyValue");
            var keyValues = new List<object> { firstKeyValue };
            if (otherKeyValues != null) keyValues.AddRange(otherKeyValues);
            return Set<TEntity>().Find(keyValues.ToArray());
        }
    
        public Task<TEntity> GetAsync<TEntity>(object firstKeyValue, params object[] otherKeyValues)
        {
            if (firstKeyValue == null) throw new ArgumentNullException("firstKeyValue");
            var keyValues = new List<object> { firstKeyValue };
            if (otherKeyValues != null) keyValues.AddRange(otherKeyValues);
            return Set<TEntity>().FindAsync(keyValues.ToArray());
        }
    
        public IQueryable<TEntity> Get<TEntity>()
        {
            return Set<TEntity>();
        }
    
        public void Create<TEntity>(TEntity entity)
        {
            if (Entry(entity).State == EntityState.Detached)
                Set<TEntity>().Add(entity);
        }
    
        public void Update<TEntity>(TEntity entity)
        {
            var entry = Entry(entity);
            entry.State = EntityState.Modified;
        }
    
        public void Delete<TEntity>(TEntity entity)
        {
            if (Entry(entity).State != EntityState.Deleted)
                Set<TEntity>().Remove(entity);
        }
    
        public void Reload<TEntity>(TEntity entity)
        {
            Entry(entity).Reload();
        }
    
        public Task ReloadAsync<TEntity>(TEntity entity)
        {
            return Entry(entity).ReloadAsync();
        }
    
        public void DiscardChanges()
        {
            foreach (var entry in ChangeTracker.Entries().Where(x => x != null))
            {
                switch (entry.State)
                {
                    case EntityState.Added:
                        entry.State = EntityState.Detached;
                        break;
                    case EntityState.Modified:
                        entry.State = EntityState.Unchanged;
                        break;
                    case EntityState.Deleted:
                        entry.Reload();
                        break;
                }
            }
        }
    
        public Task DiscardChangesAsync()
        {
            var reloadTasks = new List<Task>();
            foreach (var entry in ChangeTracker.Entries().Where(x => x != null))
            {
                switch (entry.State)
                {
                    case EntityState.Added:
                        entry.State = EntityState.Detached;
                        break;
                    case EntityState.Modified:
                        entry.State = EntityState.Unchanged;
                        break;
                    case EntityState.Deleted:
                        reloadTasks.Add(entry.ReloadAsync());
                        break;
                }
            }
            return Task.WhenAll(reloadTasks);
        }
    }
    

    ...如果您需要将UoW与命令中的查询分开,那么接口只是一种形式:

    public interface IUnitOfWork
    {
        int SaveChanges();
        Task<int> SaveChangesAsync();
        Task DiscardChangesAsync();
        void DiscardChanges();
    }
    
    public interface IReadEntities
    {
        IQueryable<TEntity> Query<TEntity>();
    
        IQueryable<TEntity> EagerLoad<TEntity>(IQueryable<TEntity> query, 
            Expression<Func<TEntity, object>> expression);
    }
    
    public interface IWriteEntities : IUnitOfWork, IReadEntities
    {
        TEntity Get<TEntity>(object firstKeyValue, params object[] otherKeyValues);
        Task<TEntity> GetAsync<TEntity>(object firstKeyValue,
            params object[] otherKeyValues);
        IQueryable<TEntity> Get<TEntity>();
        void Create<TEntity>(TEntity entity);
        void Delete<TEntity>(TEntity entity);
        void Update<TEntity>(TEntity entity);
        void Reload<TEntity>(TEntity entity);
        Task ReloadAsync<TEntity>(TEntity entity);
    }
    

    有了这个,您的接口不需要是通用的,因为这些方法是通用的.

    private readonly IWriteEntities _entities;
    ...
    _entities.Get<MyEntityA>(keyA);
    await _entities.GetAsync<MyEntityB>(keyB);
    _entities.Get<MyEntityC>.Where(...
    var results = await _entities.Query<MyEntityD>().SingleOrDefaultAsync(...
    

    您刚刚在上面的代码中保存了3个不必要的通用存储库依赖项.一个界面可以处理所有4种权利类型.

    2023-01-29 10:51 回答
  • 您可以添加以下新功能:

    public virtual void AddRange(IEnumerable<T> entities)
    {
        DbContext.Set<T>().AddRange(entities);
    }
    
    public virtual void RemoveRange(IEnumerable<T> entities)
    {
        DbContext.Set<T>().RemoveRange(entities);
    }
    

    2023-01-29 10:53 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有