Entity Framework not updating existing related entity

entity-framework entity-framework-6

Question

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.

1
0
3/20/2016 5:19:46 PM

Accepted Answer

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)

2
3/20/2016 4:59:52 PM

Popular Answer

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.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow