【问题标题】:Foreign key not updated in Entity Framework实体框架中未更新外键
【发布时间】:2019-07-24 00:38:50
【问题描述】:

我遇到了一个奇怪的情况:

public Class A 
{
      public int Id { get; set; }
}

public class B 
{ 
     public int Id { get; set; }
     [ForeignKey("A1")]
     public virtual int A_Id { get; set; }
     public virtual A A1 { get; set; }
}

当我通过修改 A1 更新 B 类型的实体时,A1.Id 被更新为新的实体 ID,但 B.A_Id 仍然分配给旧 ID。这会导致实体框架抛出错误。

我已经读过,通过将两个属性都标记为虚拟,EF 更改跟踪器会自动检测更改并更新相关的外键,但这不会发生在我身上。我还能检查什么?

【问题讨论】:

  • this question 可能会有所帮助。
  • 您需要 A_Id 属性吗?我认为您可以将其删除,并将属性保持在 A1 以上,它可能会按您的预期工作?
  • 是的,在某些情况下我确实需要它。
  • 使用的上下文是如何配置的?如果 AutoDetectChanges 被禁用,您需要自己保持 FK 和导航属性的 PK 同步。
  • 据我所知,AutoDetectChanges 没有被禁用

标签: c# sql-server asp.net-mvc entity-framework


【解决方案1】:

您如何映射 A 和 B 之间的关系将决定行为。您不需要将 A_Id 标记为虚拟。

如果您的真实架构像上面那样映射出来,它应该可以作为典型的多对一映射工作。 (许多 B 可以引用 A)关键是 B 上的 A_Id 不会更新,直到您在 DbContext 上调用 SaveChanges。调用 SaveChanges 后,FK 将更新以反映不同的 A。

例如:

       using (var context = new TestDbContext())
        {
            var a = context.As.Single(x => x.Id == 1);
            var b = context.Bs.Single(x => x.Id == 1);
            Assert.AreEqual(2, b.A_id);
            b.A = a;
            context.SaveChanges();
            Assert.AreEqual(1, b.A_Id);
        }

加载 B 时,它引用 ID = 2 的 A。我们加载 ID #1 的 A 并使用引用将其关联到 B。一旦SaveChanges 被调用,我们就可以断言B 的A_Id 现在反映了到A ID 1 的链接。

除此之外,您可能会遇到问题,具体取决于加载 A 和 B 引用的方式/位置。确保它们来自同一个 DbContext 实例。我看到人们遇到的一个大问题是传递对实体的引用。当尝试使用在其他地方加载的实体更新 DbContext 范围内的引用时,这通常会导致异常。

如果您仍然遇到问题或怀疑上述问题,请附上您的异常消息和实际代码的副本,我们可以从那里获取。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多