EF Code First:包括不处理可选关系
Posted
技术标签:
【中文标题】EF Code First:包括不处理可选关系【英文标题】:EF Code First: Include not working on optional relationship 【发布时间】:2012-04-23 12:27:52 【问题描述】:我的代码中有一个特定的查询,它需要预先加载所有相关实体(包括 ->1 个 FK 和 ->N 个 FK),因为上下文将在此之后立即处理。
我做了一个通用的“查询”方法,它采用params Expression<Func<MyItem, object>>[] includes
,然后在内部链接它们。这部分工作正常。
查询如下所示:
var item = facade.Query<MyItem>(
c => c.Childs.Select(x => x.Parent),
c => c.Childs.Select(x => x.SubChild1),
c => c.Childs.Select(x => x.SubChildNotWorking),
c => c.Childs.Select(x => x.SubChild2),
c => c.Childs.Select(x => x.SubChild3),
c => c.Childs.Select(x => x.SubChildrens)
).FirstOrDefault(c => c.Name == name);
not working 属性的映射(放置在 SubChildNotWorking 的配置中):
this.HasMany(scnw => scnw.Childs).WithOptional(c => c.SubChildNotWorking).HasForeignKey(c => c.MyForeignKey);
在所有包含中,只有SubChildNotWorking
实际上不起作用。当使用调试器检查返回的对象时,我看到了所有属性的代理。打开代理为我提供了所有其他关系的正确数据,以及 SubChildNotWorking
属性的“对象上下文已被处理异常”。
我能够发现的唯一区别是SubChildNotWorking
是一个可为空的 FK(在 DB 上具有可为空的列,在 dbcontext 中具有 WithOptional 配置),而所有其他都是配置了 WithRequired 的不可为空的 FK。
该数据库也是一个遗留数据库,不是使用 Code First 创建的,也没有遵循其约定,我只是在 DbContext 中进行了映射。其他一切正常。
我正在尝试确定是否急切加载不适用于可为空的 FK,但我找不到任何相关文档。
这是一个错误,还是预期的行为?但最重要的是,我该如何解决这个问题?
谢谢。
【问题讨论】:
如果只包含SubChildNotWorking
而没有其他子子项会怎样?那它有用吗?
您能否检查 SQL 是否正确(使用var sql = facade.Query<MyItem>(c => c.Childs.Select(x => x.SubChildNotWorking)).ToString();
)并在 SSMS 中手动测试查询是否返回预期的结果行。
能否显示 SubChildNotWorking 及其导航属性的映射?
已经说过了,它使用WithOptional和一个可以为空的FK而不是WithRequired和一个不可为空的FK,反正我会添加映射代码。
在我的场景中,类似的可选外键可以正常工作。看来,您在 db 中有外键。
【参考方案1】:
你定义了吗
[DataContract]
在你的班级(实体)上?如果是这样,请不要忘记用
注释您的 SubChild[DataMember]
或者当您对实体执行 GET 调用时,它可能最终会加载但不显示。
【讨论】:
【参考方案2】:当您使用 include 方法时,您谈论的是急切加载模式。具有关系的实体将作为集合加载。对于任何不可为空的外键,都有一个从空开始的普通集合,但对于可空的外键,则没有。在 Code First 中,您可以将导航属性设为虚拟,但这不是您的情况。可以尝试直接在 Context 上加载,例如:
var someEntity = context.someEntities.Find(1);
context.Entry(someEntity ).Reference(e => e.EntityWithFKNullable).Load();
或更短的版本:
context.EntitiesWithFKNullable.Load();
【讨论】:
以上是关于EF Code First:包括不处理可选关系的主要内容,如果未能解决你的问题,请参考以下文章
EF Core - 为啥 ClientSetNull 是可选关系的默认 OnDelete 行为(而不是 SetNull)