Entity Framework not updating existing related ent

2019-09-07 15:48发布

I have a project which uses Entity Framework extensively. And it all works fine.

However, there is one update that I am trying to make and it does not update, nor is an error thrown.

The basic process is that I take an existing entity, work with it to create a new (and different type) of entity. The new entity saves just fine, but the existing one does not.

Typically when I have encountered this, it means that the entity is not attached to the context. However, it is, and I have tried attaching it again as well as "Adding" it, but I have had no luck.

        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();

The ediDocument is saved, but the fileRowEntity is not saved.

I am tearing my hair out trying to figure this out. I have tried a second explicit save on the fileRowEntity but it comes back with zero changes saved:

        if (fileRowEntity != null)
        {
            fileRowEntity.EdiDocumentId = ediDocument.EdiDocumentId;
            fileRowEntity.Column100 = "X";
            this.Context.FileRowEntities.Attach(fileRowEntity);
            count = this.Context.SaveChanges();
        }

count is always zero, and the database is not updated.

I don't know what else to try to debug this.

2条回答
我只想做你的唯一
2楼-- · 2019-09-07 16:03

Attaching an entity to a context does not mark it as modified.

In your case, the presumption is that the context instance where you are calling SaveChanges() on, is not the same that retrieved the fileRowEntity object, so it doesn't know that it was modified (or what was modified).

When a DbContext retrieves an object from the store, it stores a copy of its original values (unless you used AsNoTracking() on that query), and whenever it detects changes by a call to DetectChanges(), which you can make explicitly, but the normal DbContext implementation will call it by itself at many points), it'll store the new object values. If there are differences between those, the next call to SaveChanges will update the entity in the store/database.

When you attach an entity but don't mark it as modified, it doesn't know anything has changed, so you can explicitly mark the entity as modified:

Using Context.Entry(fileRowEntity).State = EntityState.Modified; should tell EF that your entity was modified, and it'll generate the update command when you call SaveChanges() for the whole entity (it'll send all the field values in the UPDATE SQL). Note that doing this also attaches the entity if it was not attached to the context (no need to attach it and then set its state).

You can also mark only the properties that were modified (or change the entity OriginalValues), this way your query will be optimized (it'll only update the fields that have actually changed). It's a bit cumbersome to track those changes yourself, but if you need that extra optimization, it's worth a shot (personally, unless there's a critical load on the database server and every bit counts, I wouldn't do this, but your choice)

查看更多
该账号已被封号
3楼-- · 2019-09-07 16:11

There is a second reason for the above described behavior: This code will turn off change tracking:

 Context.Configuration.AutoDetectChangesEnabled = false;

After I found this had been set in the constructor and removed it, all worked as expected.

查看更多
登录 后发表回答