YMC
YMC

Reputation: 5462

EF 4: How to update disconnected set of data?

I'm using EF 4, POCO. The task is the following: having a long set of data of DomainObject type that need to be taken from Database and updated (add, update, delete operations) in a disconnected mode. How can I push the updated set back to the database later on? Lets assume there were no parallel changes to the table since we load data. I know context.SaveChanges() do the update, but the question is how to put all the changes back to DbSet from kinda List, or maybe there is a way to work directly with DbSet in disconnected mode? Thanks!

Upvotes: 4

Views: 4408

Answers (2)

Ladislav Mrnka
Ladislav Mrnka

Reputation: 364409

Self-tracking entities are feature of EDMX + ObjectContext API so if you have your mapping / code dependent on DbContext API (you mentioned DbSet) you can't use them. Self-tracking entities are implementation of change set pattern (like old data set). Some reference on SO:

If you don't use Self-tracking entities the answer is pretty simple - you must say EF what changes you did. Once using detached entities you must attach entities back to a new context and manually say exactly what you did = what is inserted, updated, deleted and how did you change relations. The key component in this process is ObjectStateManager in ObjectContext API (context.ObjectStateManager) orDbChangeTracker in DbContext API (context.ChangeTracker). This is extremely hard when dealing with relation so many of us usually using another process: we load the entity graph again and merge changes from detached entity graph to attached entity graph. Some references:

Be aware that whole your process can be pretty slow depending on number of updates you want to do. The reason is that EF doesn't support command batching so each insert, update, delete is executed in a separate round trip to the database. If you update 100.000 complex objects you can expect that execution of SaveChanges takes several minutes.

Edit:

In some very special scenarios where you work only with entities without relations you can use a trick to transfer information about "changes":

public void ProcessChanges(IEnumerable<DomainObject> entities)
{
    foreach(var entity in entities)
    {
        if (entity.Id == 0)
        {
            // New entity
        }
        else if (entity.Id > 0)
        {
            // Modified entity (you cannot say if entity war really modified,
            // you must update it always).
        }
        else
        {
            // Use negative Id (origId * -1) to mark entity as deleted
            // reverse Id and delete entity
        }
    }
}

This works only for flat objects with simple key.

Upvotes: 7

Related Questions