我想知道是否有可能为给定类的某些子类预加载相关实体。
类结构如下
订单与许多基本子订单类(SuborderBase)有关。 MySubOrder 类继承自 SuborderBase。我想在加载订单时为 Include() 指定路径以加载 MySubOrder 相关实体(客户),但我收到一个错误,声称 SuborderBase 和客户之间没有关系。但是 MySubOrder 和 Customer 之间存在关系。
下面是失败的查询
Context.Orders.Include("SubOrderBases").Include("SubOrderBases.Customers")
如何明确指定?
更新。实体方案如下
最佳答案
这是一个只需要一次往返的解决方案:
var orders = Context.Orders
.Select(o => new
{
Order = o,
SubOrderBases = o.SubOrderBases.Where(s => !(s is MyOrder)),
MyOrdersWithCustomers = o.SubOrderBases.OfType<MyOrder>()
.Select(m => new
{
MyOrder = m,
Customers = m.Customers
})
})
.ToList() // <- query is executed here, the rest happens in memory
.Select(a =>
{
a.Order.SubOrderBases = new List<SubOrderBase>(
a.SubOrderBases.Concat(
a.MyOrdersWithCustomers.Select(m =>
{
m.MyOrder.Customers = m.Customers;
return m.MyOrder;
})));
return a.Order;
})
.ToList();
它基本上是对匿名类型集合的投影。之后查询结果被转换为内存中的实体和导航属性。 (它也适用于禁用跟踪。)
如果您不需要实体,您可以省略第一个 ToList()
之后的整个部分,直接使用匿名对象中的结果。
如果您必须修改此对象图并需要更改跟踪,我不确定这种方法是否安全,因为在加载数据时导航属性未完全设置 - 例如 MyOrder.Customers
在投影之后为 null
,然后在内存中设置关系属性可能会被检测为修改,但它不是,并在您调用 SaveChanges
时造成麻烦。
预测是针对只读场景,而不是针对修改。如果您需要更改跟踪,可能更安全的方法是在多个往返中加载完整实体,因为在您的情况下无法在单个往返中使用 Include
来加载整个对象图。
关于c# - Entity Framework - 子类相关对象的预加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7635152/