为了账号安全,请及时绑定邮箱和手机立即绑定

EF 6 添加后获取实体

EF 6 添加后获取实体

C#
吃鸡游戏 2023-06-25 13:28:19
我在 .NET MVC 应用程序中使用 EF 6。我有这些课程:public class Member {    public int ID { get; set; }    public string Name { get; set; }    public int FactoryID { get; set; }    public Factory Factory { get; set; }}public class Factory{    public int ID { get; set; }    public string Name { get; set; }    public virtual ICollection<Member> Members { get; set; }}要添加的代码:var newMember = new Member();newMember.Name = 1;newMember.FactoryID = 2;context.Members.Add(newMember);context.SaveChanges();代码获取:var member = context.Members.SingleOrDefault(x => x.ID == id);var factory = member.Factory;因此,当我添加Member一个 API 调用时,然后再加入Member另一个 API 调用,然后Member.Factory就定义了。Member当我尝试添加后立即获取时,Member.Factory是NULL.其原因何在?又该如何解决呢?
查看完整描述

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 和保存的引用。无需返回完整的数据和参考。


查看完整回答
反对 回复 2023-06-25
  • 1 回答
  • 0 关注
  • 140 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信