为什么EF不将NULL外键保存到数据库?

本文关键字:保存 数据库 EF 不将 NULL 为什么 | 更新日期: 2023-09-27 18:13:09

我已经搜索了…我保证。我最接近答案的是一个帖子,其中使用了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更改为另一个int,则在此调用之后将更改持久化到数据库中。但是,如果我像本例中那样将值设为空,以"清除"外键引用,则返回原始值。

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

所以我的问题是为什么ChangeTracker(或任何自动生成的代码)允许FK从一个int值更改为另一个,但它不会坚持null?我如何"修复"它或围绕问题工作?

谢谢。J

更新:

键绝对是可空的。在DB和类定义中都有。另一篇文章的链接似乎是一个不同的场景…他们希望在删除外部实体时自动使外键为空。(我会仔细看看,只是为了确保没有答案,但这似乎是一个不同的问题。)只是为了好玩,我创建了一个新对象并复制了属性,除了nav属性,并将FK属性设置为null,这确实有效。空FK被持久化,并且导航属性和外键属性都为空。因此,它与更改跟踪器以及它如何维护对实体对象的引用有关,尽管它具有所有poco特性。所以,至少,我有一个变通的办法。但我想了解到底发生了什么,以及如何解决它。

解决方案:

我刚刚发现,今天早上,我对T4模板所做的更改必须被覆盖,在某些时候,我丢失了一行设置ProxyCreationEnabled为false的DBContext…一旦我意识到这一点并进行了修复,我就能够正确地持久化更改。因此,实际上,我正在与更改跟踪器中的某些东西作斗争,因为它正在为从DB检索的实体创建动态代理。(我认为)。

为什么EF不将NULL外键保存到数据库?

我刚刚发现,今天早上,我对T4模板所做的更改必须被覆盖,在某些时候,我丢失了一行设置ProxyCreationEnabled为false的DBContext…一旦我意识到这一点并进行了修复,我就能够正确地持久化更改。因此,实际上,我正在与更改跟踪器中的某些东西作斗争,因为它正在为从DB检索的实体创建动态代理。(我认为)。