【发布时间】: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