【问题标题】:How can I implement multiple Include in Entity Framework?如何在实体框架中实现多个包含?
【发布时间】:2020-12-13 08:53:46
【问题描述】:

我使用实体框架 6。我有一个带有多个导航属性的 Transaction 对象。使用多个 Include 很容易实现预加载。

 var aa = db.Transactions.Include(p => p.Account).Include(p => p.Instrument);

如果要包含的字段是参数,我该如何实现?

var aa = db.Transactions.IncludeMore(delegatesToBeIncluded);   

如果delegatesToBeIncluded 为空,则没有要包含的内容。

https://stackoverflow.com/a/38823723/5852947 这与我想要的类似,但它使用字符串而不是委托。

https://stackoverflow.com/a/35889204/5852947这也很有意思。

How to pass lambda 'include' with multiple levels in Entity Framework Core?这个重点是多层次(我有一个层次)

https://stackoverflow.com/a/52156692/5852947这也很有希望。

我应该往哪个方向走?

修订版 1:为什么我需要这个? 基于aa 的元素将创建新对象。我意识到在每个对象创建时,EF 都会读取数据库(使用延迟加载)。它只有 50 毫秒,但它会重复 n 次。 这个函数是在模板类中实现的,所以Transactions也是一个参数。

修订版 2:在完整的代码中,有过滤(准确地说是分页),然后是 ToList()。它在模板函数中实现的棘手部分。 dbTableSelector 是代表:readonly Func<MainDbContext, DbSet<TDbTable>> dbTableSelector;

 var myList = dbTableSelector(db).Where(WhereCondition).
             Skip(numberOfSkippedRows).Take(PageSize).OrderBy(OrderByCondition).ToList();

之后,我将myList 的每个元素转换为另一种类型的对象。这是为每个元素一个一个激活延迟加载的地方。这就是我尝试使用 Include 的原因。如果dbTableSelector(db) 返回Transactions 我必须在它返回时包含不同的元素让我们说Instruments。所以 IncludeMore 应该有一个 List 参数来定义要包含的字段。

【问题讨论】:

  • 你想做什么?首先,你没有加载任何东西。 aa 是一个尚未执行的可查询对象。如果 final 查询的 Select 触及任何相关实体,它们也会被加载,即使没有 Include。其次,由于aa 是可查询的,您可以根据需要“附加”IncludeWhere 调用,例如foreach(var exp in expressions){ aa=aa.Include(exp);}
  • 您需要动态附加Include 调用的唯一 原因是,如果您尝试创建动态查询生成器而不实际知道类型是什么。由于您已经知道类型是什么,因此尝试“参数化”调用最终会比简单地使用每种情况下需要的 Include 调用更加冗长。
  • 这不一定是真的。早在 3 月,我不得不处理一个从一百万个地方调用的方法,而 Include()s 是您可以要求的最糟糕的妥协。它必须是所有事物的联合,因为糟糕的方法无法确定可能使用哪个链接实体。
  • @PanagiotisKanavos 请参阅修订版 1
  • 这只是重复了问题所说的内容,因此所有 cmets 仍然适用。它甚至不准确,正是因为aa 仍然是一个不完整的查询。您需要对其进行迭代或使用ToList()ToArray() 等来执行它。如果您编写需要相关实体的Select,它们将被加载。

标签: c# entity-framework eager-loading


【解决方案1】:

这里是解决方案。它基于this

public static class IQueryableExtensions
{
    public static IQueryable<T> IncludeMultiple<T, TProperty>(this IQueryable<T> query,
        Expression<Func<T, TProperty>>[] includeDelegates) where T : class
    {
        foreach (var includeDelegate in includeDelegates)
            query = query.Include(includeDelegate);
        return query;
    }
}

这是召唤:

var pathsA = new Expression<Func<ViewTransaction, object>>[2] { p => p.Account, p => p.Instrument };
var pathsB = new Expression<Func<ViewTransaction, object>>[1] { p => p.Account};
var pathsC = Array.Empty<Expression<Func<ViewTransaction, object>>>();


var a = db.ViewTransactions.IncludeMultiple(pathsA).Single(e => e.Id == 100);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-22
    相关资源
    最近更新 更多