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&lt;MyItem&gt;(c =&gt; c.Childs.Select(x =&gt; 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 Code First 学习笔记:关系

EF Code First关系规则及配置

EF Core - 为啥 ClientSetNull 是可选关系的默认 OnDelete 行为(而不是 SetNull)

EF Code First学习笔记

EF Code First 导航属性 与外键

EF Code First 导航属性 与外键