【问题标题】:Why won't EF persist a NULL foreign key to the DB?为什么 EF 不会将 NULL 外键持久保存到数据库?
【发布时间】:2017-02-23 00:20:17
【问题描述】:

我已经搜索过了……我保证。我最接近答案的是使用 EF 自我跟踪实体的帖子,但我不明白如何使其适用于我的情况。

就我而言,我有一条现有记录,我想将值从 int 更改为 NULL。

表格伪代码:

PICKLIST_VALUE
Picklist ID (int, PK, Identity, NOT NULL)
PicklistValue (String, NOT NULL)

PERSON
Person_ID (int, PK,Identity, NOT NULL)
Person_Name (varchar(100), NOT NULL)
Person_Prefix (int, FK, NULL)
Person_Suffix (int, FK, NULL)
FOREIGN KEY (Person_Prefix) REFERENCES PICKLIST_VALUES.Picklist_ID
FOREIGN KEY (Person_Suffix) REFERENCES PICKLIST_VALUES.Picklist_ID

我使用的是 EF6,首先是 DB...使用基于 Magnus Montin 在 https://blog.magnusmontin.net/2013/05/30/generic-dal-using-entity-framework/ 上的帖子的 DAL

在我的代码中,每个实体(表)都有 POCO 定义。 Person 可以有前缀(Mr.、Mrs. 等),Person 可以有后缀(Jr.、Sr. 等)。如果我不小心设置了一个后缀,然后意识到它不正确,我想成为可以去掉后缀:

someperson.Person_Suffix = null;  // Set FK property to null
someperson.PICKLIST_VALUE = null; // Set navigation property to null
someperson.EntityState = EntityStates.Modified;
DAL.UpdatePerson(someperson);

UpdatePerson 方法根据 DAL 文章解析到这个位:

public virtual void Update(params T[] items)
{
  using (var context = new Entities())
  {
    DbSet<T> dbSet = context.Set<T>();

    foreach (T item in items)
    {
      dbSet.Add(item);
      foreach (DbEntityEntry<IEntity> entry in context.ChangeTracker.Entries<IEntity>())
      {
        IEntity entity = entry.Entity;
        entry.State = GetEntityState(entity.EntityState);
      }
    }

    context.SaveChanges();
  }
}

protected static System.Data.Entity.EntityState GetEntityState(CB.DomainModel.EntityState entityState)
{
  switch (entityState)
  {
    case DomainModel.EntityState.Unchanged:
      return System.Data.Entity.EntityState.Unchanged;
    case DomainModel.EntityState.Added:
      return System.Data.Entity.EntityState.Added;
    case DomainModel.EntityState.Modified:
      return System.Data.Entity.EntityState.Modified;
    case DomainModel.EntityState.Deleted:
      return System.Data.Entity.EntityState.Deleted;
    default:
      return System.Data.Entity.EntityState.Detached;
  }
}

我不太了解 EF 的内容以及 .edmx 和 T4 模板代码的作用。如果我这样做了,我可能会弄清楚这一点。但是,如果我将值从一个 int 更改为另一个,则在此调用之后更改将持久保存到数据库中。但是,如果我将这些值设为空,如本例所示,以“清除”外键引用,则原始值会返回。

它必须与对象在添加到 dbSet 后向 ChangeTracker 注册的方式有关。在此之前,它只是一个普通的旧对象。

所以我的问题是为什么 ChangeTracker(或任何自动生成的代码)允许 FK 从一个 int 值更改为另一个,但它不会保持 null?我该如何“修复”它或解决这个问题?

谢谢。 J

更新:

密钥绝对可以为空。在数据库和类定义中。另一个帖子的链接似乎是一个不同的场景......他们希望在删除外部实体时自动使外键为空。 (我会仔细看看,以确保那里没有答案,但这似乎是一个不同的问题。)只是为了好玩,我创建了一个新对象并复制了属性,除了导航属性并将我要删除的 FK 属性设置为 null 并且确实有效。空 FK 被持久化,并且 nav 道具和外键道具都为空。因此,它与更改跟踪器以及它如何维护对实体对象的引用有关,尽管它具有所有 POCO 特性。所以,至少,我有一个解决方法。但我想了解实际发生的情况以及如何解决它。

解决方案:

今天早上,我刚刚发现,我对 T4 模板所做的更改在某些时候一定被覆盖了,并且我丢失了一条将 DBContext 的 ProxyCreationEnabled 设置为 false 的行...一旦我意识到这一点并且放入修复程序,我能够正确地保留更改。因此,实际上,我在更改跟踪器中与某些东西作斗争,因为它正在为从数据库中检索到的实体创建动态代理。 (我认为。)

【问题讨论】:

  • 如果Person 类有一个不可为空的外键属性(即Person 有类似:public int Person_PrefixId { get; set; },那么关系是必需的,而您不能Person_Suffix 设置为NULL。如果要使关系可选,则外键属性应该可以为空:public int? Person_PrefixId { get; set; }
  • 也可以通过打开EF图来验证外键字段是否为空,选择Person_Suffix或者Person_Prefix字段,在属性窗口中勾选Nullable属性。
  • 为什么要将属性和相关的导航属性都设置为空?
  • 您只将导航属性设置为 NULL,而不是 FK。 EF 不会将 FK 设置为 null,只是因为您将导航属性设置为 null(因为您甚至可能一开始都没有检索到)。

标签: c# entity-framework


【解决方案1】:

今天早上,我刚刚发现,我对 T4 模板所做的更改在某些时候一定被覆盖了,并且我丢失了一条将 DBContext 的 ProxyCreationEnabled 设置为 false 的行...一旦我意识到这一点并且放入修复程序,我能够正确地保留更改。因此,实际上,我在更改跟踪器中与某些东西作斗争,因为它正在为从数据库中检索到的实体创建动态代理。 (我认为。)

【讨论】:

    猜你喜欢
    • 2014-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 2011-04-10
    • 2022-11-24
    • 1970-01-01
    相关资源
    最近更新 更多