Eager默认情况下使用通用存储库中的实体框架加载ALL

时间:2014-01-25 20:36:19

标签: c# asp.net-mvc linq entity-framework repository-pattern

我目前正在实现存储库模式,它允许我将我的类和上下文传递到通用存储库。这很完美。我感兴趣的方法是Get and Find。 find允许我指定和“命令”,一些“where”语句和一些“include”语句。这很理想。

public class GeneralRepository<TEntity> : IGeneralRepository<TEntity> where TEntity : class
{

    readonly GamesContext context;
    readonly DbSet<TEntity> db;

    public GeneralRepository(GamesContext existingContext)
    {
        context = existingContext;
        db = context.Set<TEntity>();
    }

    public TEntity Get(object id)
    {
        return db.Find(id);
    }

    public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "")
    {
        IQueryable<TEntity> query = db;

        if (filter != null)
        {
            query = query.Where(filter);
        }

        foreach (var includeProperty in includeProperties.Split
           (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
        {
            query = query.Include(includeProperty);
        }

        if (orderBy != null)
        {
           return orderBy(query).ToList();
        }
        else
        {
           return query.ToList();
        }
    }
}

我的问题是,当我使用Get方法时,我宁愿它返回完整的对象图。延迟加载暂时关闭,但是为了急切加载我需要添加相关的包含,只有这样才能打败做通用存储库的对象。

我知道我可以使用find方法,但默认情况下使用get方法返回所有相关数据要快得多。

默认情况下我是如何获得所有(急切加载全部)的?

感谢。

2 个答案:

答案 0 :(得分:4)

这是一个坏主意。特别是如果您计划进一步构建应用程序。这是解决性能瓶颈和OutOfMemory异常的道路。

我发现通用存储库也是反模式的。随着时间的推移,您将意识到您需要在Get方法中添加越来越多的功能,最终它只会复制DbContext的实现。

实际上,您当前的实现不会出于任何隔离目的。为什么不直接使用DbContext?

我建议转储Generic东西的想法,并使用小型Query类,只能以受控方式检索所需的实体,而不是每个人都能检索。看看this

要回答您的问题,实体框架没有提供IncludeAll的选项。你可以用反射进行破解,但我不打算在这里给出解决方案,因为这只是一种不好的做法。

答案 1 :(得分:1)

使用通用存储库模式,这是一个很好的方法,可以满足您的需求。希望它可以帮助某人,它易于使用,并且足够简单,可以包含在您的代码中。

IRepository.cs:

public interface IRepository<TEntity> where TEntity : class
{
    IEnumerable<TEntity> GetAll(params Expression<Func<TEntity, object>>[] properties);
}

Repository.cs

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{    
    private readonly DbSet<TEntity> _dbset;

    public Repository(DbSet<TEntity> dbset)
    {
        _dbset = dbset;
    }

    public virtual IEnumerable<TEntity> GetAll(params Expression<Func<TEntity, object>>[] properties)
    {  
        if (properties == null) 
            throw new ArgumentNullException(nameof(properties));

        var query = _dbset as IQueryable<TEntity>; // _dbSet = dbContext.Set<TEntity>()

        query = properties
                   .Aggregate(query, (current, property) => current.Include(property));

        return query.AsNoTracking().ToList(); //readonly
    }
}

解释如何使用的一些模型:

public class User
{
    public int Id {get; set;}
    public string Name {get; set;}
    public List<Address> Address {get; set;}
    public List<Cart> Carts {get; set;}
}

使用方法:

var repository = new Repository<User>();
var users = repository.GetAll(d => d.Address, d => d.Carts);

参考:Link