嵌套 tph 继承成员的 ef-core 负载收集属性
Posted
技术标签:
【中文标题】嵌套 tph 继承成员的 ef-core 负载收集属性【英文标题】:ef-core load collection property of nested tph inherited member 【发布时间】:2017-01-13 14:39:31 【问题描述】:给定以下类结构
public class Parent
public Guid Id get;
public List<BaseChild> Children get; set;
public abstract class BaseChild
public int Id get; set;
public string ChildName get; set;
public class NormalChild : BaseChild
public DateTime BirthDate get; set;
public class RichChild : BaseChild
public List<OffshoreAccount> OffshoreAccounts get; set;
public class OffshoreAccount
public string AccountNumber get; set;
public AccountInfo AccountInfo get; set;
查询父母数据以包含子女离岸账户信息的最佳方式是什么?我想出了下面的解决方案,使用 ef-core 的显式加载,但感觉不对。有没有更优雅的解决方案?
var parent = Context.Set<Parent>()
.Where(o => o.Id == Guid.Parse(parentId))
.Include(o => o.Children)
.SingleOrDefault();
foreach (var child in parent.Children.OfType<RichChild>())
Context.Entry<RichChild>(child).Collection(f => f.OffshoreAccounts).Load();
foreach (var account in child.OffshoreAccounts)
Context.Entry<OffshoreAccount>(account).Reference(f => f.AccountInfo).Load();
【问题讨论】:
请将childs
重命名为children
。
什么是AccountInfo
?
为了避免加载相关实体的代码开销,您应该让 EF 通过启用 EF 延迟加载或急切加载来完成这项工作。在这里查看更多信息:msdn.microsoft.com/en-us/library/jj574232(v=vs.113).aspx
@Felix 目前 EF Core 中没有延迟加载,也没有急切加载派生类属性的语法。
【参考方案1】:
更新(EF Core 2.1+):
从 v2.1 开始,EF Core 原生支持 Include on derived types 通过 C# cast 或 as
运算符。
例如
.Include(e => e.Children)
.ThenInclude(e => ((RichChild)e).OffshoreAccounts)
.ThenInclude(e => e.AccountInfo)
或
.Include(e => e.Children)
.ThenInclude(e => (e as RichChild).OffshoreAccounts)
.ThenInclude(e => e.AccountInfo)
文档声称Include
的string
重载也可以使用,例如根据它
.Include(e => "Children.OffshoreAccounts.AccountInfo")
应该也可以,但它没有(检查到 v3.1.4)。
原文:
目前无法在父查询中实现这一点,但可以通过使用Entry
、Collection
、Query
、Include
/ThenInclude
和@987654335 的组合来改进显式加载@调用:
var parent = Context.Set<Parent>()
.Where(o => o.Id == Guid.Parse(parentId))
.Include(o => o.Children)
.SingleOrDefault();
Context.Entry(parent).Collection(e => e.Children)
.Query().OfType<RichChild>()
.Include(e => e.OffshoreAccounts)
.ThenInclude(e => e.AccountInfo)
.Load();
【讨论】:
我怎样才能将它扩展到更低的 tph?为了给出上下文,我有以下结构(在表单构建器上工作): Form.Questions.Control 控件是下拉或 TextField 等类的基本类型。 @Peter-Paul 所以你想包含控制的部分吗?我不能确切地说 - 因为上面是某种黑客,因此一般不可扩展,您可以考虑使用示例 minimal reproducible example 发布您自己的具体问题。 我最终做到了,首先获取表单,然后遍历问题以逐个控件添加特定于类的属性。很多数据库调用,但它完成了工作。 @IvanStoev 你有提到这个的 github 问题链接或文档吗? @Dealdiane #3910【参考方案2】:在当前的 EFCore (2.1.1) 中,您可以在 ThenInclude
中使用类型转换来获得您正在寻找的结果:
var parent = _context.Set<Parent>()
.Include(x => x.Children)
.ThenInclude(y => (y as RichChild).OffshoreAccounts)
.SingleOrDefault();
【讨论】:
以上是关于嵌套 tph 继承成员的 ef-core 负载收集属性的主要内容,如果未能解决你的问题,请参考以下文章
Entity Framework 6 Recipes 2nd Edition(10-10)译 - > 为TPH继承的插入更新删除操作映射到存储过程