我有一个广泛使用Entity Framework的项目。一切正常。
但是,我尝试进行一次更新,它不会更新,也不会抛出错误。
基本过程是我采用现有实体,使用它来创建一个新的(和不同类型)实体。新实体保存得很好,但现有实体没有。
通常,当我遇到这个时,意味着该实体未附加到上下文。然而,它是,并且我已经尝试再次添加它以及“添加”它,但我没有运气。
if (fileRowEntity != null)
{
this.Context.FileRowEntities.Attach(fileRowEntity);
fileRowEntity.FileRowStatusId = (int)FileRowStatus.Converted;
fileRowEntity.EdiDocument = ediDocument;
}
ediDocument.InsertedDate = DateTime.Now;
ediDocument.EdiDocumentGuid = Guid.NewGuid();
ediDocument.DocumentMetatdata = null;
this.Context.EdiDocuments.Add(ediDocument);
var count = this.Context.SaveChanges();
ediDocument
已保存,但fileRowEntity
未保存。
我正试图弄清楚我的头发。我已尝试在fileRowEntity
上进行第二次显式保存,但它保存了零更改:
if (fileRowEntity != null)
{
fileRowEntity.EdiDocumentId = ediDocument.EdiDocumentId;
fileRowEntity.Column100 = "X";
this.Context.FileRowEntities.Attach(fileRowEntity);
count = this.Context.SaveChanges();
}
count
始终为零,数据库未更新。
我不知道还有什么可以尝试调试它。
答案 0 :(得分:2)
将实体附加到上下文不会将其标记为已修改。
在您的情况下,假设您调用SaveChanges()
的上下文实例与检索fileRowEntity
对象的内容实例不同,因此它不知道它已被修改(或者被修改的内容)。
当DbContext
从商店检索对象时,它会存储其原始值的副本(除非您在该查询中使用AsNoTracking()
),并且每当它通过调用{{ 1}},你可以明确地做,但正常的DetectChanges()
实现将在很多点自己调用它),它将存储新的对象值。如果它们之间存在差异,则对DbContext
的下一次调用将更新商店/数据库中的实体。
当您附加实体但未将其标记为已修改时,它不知道任何内容已更改,因此您可以明确地将该实体标记为已修改:
使用SaveChanges
应告诉EF您的实体已被修改,并且当您为整个实体调用Context.Entry(fileRowEntity).State = EntityState.Modified;
时它将生成更新命令(它将发送{的所有字段值{1}} SQL)。请注意,如果实体没有附加到上下文(不需要附加它然后设置其状态),这样做也会附加实体。
您还可以仅标记已修改的属性(或更改实体SaveChanges()
),这样您的查询将得到优化(它只会更新实际更改的字段)。自己跟踪这些更改有点麻烦,但是如果你需要额外的优化,那么值得一试(就个人而言,除非数据库服务器上存在关键负载并且每个位都很重要,我不会这样做,但是你的选择)
答案 1 :(得分:1)
出现上述行为的第二个原因是:此代码将关闭更改跟踪:
Context.Configuration.AutoDetectChangesEnabled = false;
在我发现已在构造函数中设置并删除它之后,所有工作都按预期工作。