为什么EF不会将NULL外键持久存储到数据库中?

时间:2016-10-13 18:29:25

标签: c# entity-framework

我搜索过......我保证。我最接近答案的是一个使用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,数据库...基于Magnus Montin在https://blog.magnusmontin.net/2013/05/30/generic-dal-using-entity-framework/发布的DAL

在我的代码中,我有每个实体(表)的POCO定义。一个人可以有一个前缀(先生,夫人等),一个人可以有一个后缀(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,则在此调用之后更改将持久保存到数据库。但是,如果我使值为null(如本例所示),则“清除”外键引用,原始值将返回。

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

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

感谢。 Ĵ

更新:

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

解决方案:

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

1 个答案:

答案 0 :(得分:0)

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