【发布时间】: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是可查询的,您可以根据需要“附加”Include或Where调用,例如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