【问题标题】:Why is EF eager loading include not working as expected?为什么 EF 急切加载包括未按预期工作?
【发布时间】:2014-01-15 16:28:36
【问题描述】:

我有这个仓库,

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
    private readonly DbContext context;
    private readonly DbSet<TEntity> dbEntitySet;

    public Repository(DbContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        this.context = context;
        this.dbEntitySet = context.Set<TEntity>();
    }

    public IEnumerable<TEntity> GetAll()
    {
        return this.dbEntitySet;
    }

    public IEnumerable<TEntity> GetAll(string include)
    {
        return this.dbEntitySet.Include(include);
    }

    public IEnumerable<TEntity> GetAll(string[] includes)
    {
        foreach (var include in includes)
            this.dbEntitySet.Include(include);

        return this.dbEntitySet;
    }

    public void Create(TEntity model)
    {
        this.dbEntitySet.Add(model);
    }

    public void Update(TEntity model)
    {
        this.context.Entry<TEntity>(model).State = EntityState.Modified;
    }

    public void Remove(TEntity model)
    {
        this.context.Entry<TEntity>(model).State = EntityState.Deleted;
    }

    public void Dispose()
    {
        this.context.Dispose();
    }
}

我遇到的问题是这种方法:

public IEnumerable<TEntity> GetAll(string[] includes)
{
    foreach (var include in includes)
        this.dbEntitySet.Include(include);

    return this.dbEntitySet;
}

当我运行它并在返回之前放置一个断点时,就好像 foreach 被忽略了。

上面的方法效果很好:

public IEnumerable<TEntity> GetAll(string include)
{
    return this.dbEntitySet.Include(include);
}

要调用它,我基本上是这样做的:

var a = this.Repository.GetAll(new string[] { "ForbiddenUsers", "ForbiddenGroups" }).ToList();

返回结果但不包括包含:D 如果我将调用修改为:

var a = this.Repository.GetAll("ForbiddenUsers").ToList();

它工作正常。

谁能给我一个解决方案?

【问题讨论】:

  • +1 表示 GetAll 方法的想法!有用!

标签: c# entity-framework eager-loading


【解决方案1】:

将您的方法更改为如下所示:

public IEnumerable<TEntity> GetAll(string[] includes)
{
    var query = this.dbEntitySet;

    foreach (var include in includes)
        query = query.Include(include);

    return query;
}

Include 方法不会改变 DbSet,它只会返回一个新的 DbQuery 并包含您的包含。

【讨论】:

  • 对于第一个,我得到一个无效的强制转换异常,对于第二个,当我运行它时它会出错(它编译得很好)。我打算再做几个测试看看问题出在哪里
  • 是的,你的第二种方法的问题是你包含认为我正在尝试创建一个导航属性,其中包含所有不起作用的连接字符串
  • 啊,好的。我以为你可以做到这一点,但我想我错了。我已经删除了第二个示例。
【解决方案2】:

此代码不正确:

public IEnumerable<TEntity> GetAll(string[] includes)
{
    foreach (var include in includes)
       this.dbEntitySet.Include(include);

    return this.dbEntitySet;
}

正确的代码如下:

public IEnumerable<TEntity> GetAll(string[] includes)
{
     IQueryable<T> query = this.dbEntitySet;

     foreach (var include in includes)
         query = query.Include(include);

    return query;
}

在你的位置,我将使用这样的 Lambda 表达式:

public IEnumerable<TEntity> GetAll(Expression<Func<T, object>>[] includes)
{
     IQueryable<T> query = this.dbEntitySet;

     foreach (var include in includes)
         query = query.Include(include);

     return query;
}

【讨论】:

  • Lambda 在这里可能不起作用。 Expression&lt;Func&lt;T, TRet&gt;&gt; 不能转换为 Expression&lt;Func&lt;T, object&gt;&gt;,我相信 lambda 中的强制转换会释放魔法。
  • @CoryNelson 我从来没有提到过表达式>。 Expression> 对我很有效。您在我的代码中哪里看到了 TRe?
  • 确实你没有提到它——我要指出的是每个人的 lambdas 是某种类型的——不是object——所以我没有看不到您的方法的有用性,因为 Func&lt;T, int&gt; 等的表达式不能转换为 Func&lt;T, object&gt; 的表达式。
  • 在谈论之前你测试过我的代码吗?也许它不适用于您的场景,但对我来说效果很好。您可以查看此示例 => blogs.msdn.com/b/wriju/archive/2013/08/23/…
  • @CodeNotFound 您的第一个查询与我的问题相同。尽管它确实可以编译,但它似乎忽略了包含。还有,你怎么称呼第二种方法??
猜你喜欢
  • 1970-01-01
  • 2011-12-24
  • 1970-01-01
  • 2021-01-26
  • 2021-11-27
  • 1970-01-01
  • 2017-12-26
  • 2015-10-12
  • 1970-01-01
相关资源
最近更新 更多