1 回答
TA贡献1982条经验 获得超2个赞
它有时会起作用但其他时候不起作用的原因是,当您通过 ID 引用实体时,EF 将提供它知道的相关实体。如果启用延迟加载,EF 将前往数据库拉回任何它不知道的相关实体。然而,当涉及到序列化响应时,延迟加载可能会导致性能问题或循环引用错误。
例如,关闭延迟加载:
如果我做类似的事情:
using (var context = new MyContext())
{
var member = new Member
{
FactoryId = 3;
// ...
}
context.Members.Add(member);
context.SaveChanges();
return member;
}
返回的成员的“Factory”引用将为#null,因为 EF 上下文不知道 Factory ID 3 实际是什么。如果工厂 ID #3 的数据记录存在,但上下文不知道,则插入将会成功。
如果在另一个例子中我做了这样的事情:
using (var context = new MyContext())
{
// Call some code using this context that results in the following running...
var factory = context.Factories.Single(x => x.FactoryId == 3);
// more code...
var member = new Member
{
FactoryId = 3;
// ...
}
context.Members.Add(member);
context.SaveChanges();
return member;
}
在这种情况下,EF 将返回 Factory #3 以及成员,因为上下文实例知道 Factory #3。保存成员时,会自动关联已知参考。
上面的示例在 using 块中使用了 DbContext,这使得场景看起来很明显,但是,对于使用 IoC 容器将 DbContext 范围限定为请求的代码,例如,对于跨各种不同的给定场景,它可能不太清晰。可以调用这些方法来确定 DbContext 可能知道或不知道哪些实体。
在处理引用时,您希望返回有关实体及其引用的详细信息,或者以下代码将受益于访问引用,我的典型建议是设置引用,而不是实体中的 FK。通过这种方式,您可以确保您正在创建的实体处于完整且适合目的的状态。
例如:
using (var context = new MyContext())
{
var factory = context.Factories.Single(x => x.FactoryId == factoryId);
var member = new Member
{
Factory = factory;
// ...
}
context.Members.Add(member);
context.SaveChanges();
return member;
}
我避免在实体中完全公开 FK 以强制使用引用,并使用影子属性 (EFCore) 和映射 (EF6) 来确保 FK 在我的实体中不可访问。FK 的问题在于,当编辑同时具有引用和 FK 列的实体时,有 2 个事实来源。更新 Factory 是否会更改工厂引用,或者更新 FactoryId 是否会更改?如果我有一个指向 Factory ID 3 的 Factory 引用,但我将 Member 上的 FactoryId 更改为 4,该怎么办?有些代码可能依赖于 FK,而其他代码可能会转到工厂参考。
显式地使用引用意味着相关实体在此时被断言(而不是等待 SaveChanges 上的任意数量的 FK 违规)。它将使用上下文已加载的任何加载引用,或者如果需要则转到数据库。
我确实使用 FK 而不是引用来进行批量操作,我只想尽快更新或插入大量信息。在这些情况下,我使用有界上下文,其中包含带有 FK 的简单实体定义,并且没有创建、设置 FK 和保存的引用。无需返回完整的数据和参考。
- 1 回答
- 0 关注
- 140 浏览
添加回答
举报