实体框架不更新现有相关实体

时间:2016-03-20 16:26:53

标签: entity-framework entity-framework-6

我有一个广泛使用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始终为零,数据库未更新。

我不知道还有什么可以尝试调试它。

2 个答案:

答案 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;

在我发现已在构造函数中设置并删除它之后,所有工作都按预期工作。