0

I use EntityFramework 4.1.

What I want to achieve is, whenever SaveChanges method is called on entities that are FooEntity, first I want to UPDATE those entities and then DELETE after.

I try to override the default behaviour as below, but I can't achieve what I want: It updates on the Db. but not DELETES.

How can I achieve this?

public override int SaveChanges()
        {
            var entitiesMarkedAsDelete = ChangeTracker.Entries<FooEntity>()
                                    .Where(e => e.State==EntityState.Deleted);

            foreach (var e in entitiesMarkedAsDelete)
            {
                e.State = EntityState.Modified;
            }

            base.SaveChanges(); // To enforce an UPDATE first

            // Now, I try to re-mark them to DELETE
            foreach (var e in entitiesMarkedAsDelete)
            {
                e.State = EntityState.Deleted;
            }

            base.SaveChanges(); // And hope that they will be deleted

            // RESULT: 1st call of base.Savechanges() updates the entities
            //       but the 2nd call of base.Savechanges() does not make any changes on the UPDATED 
            //      entities -and they are NOT DELETED.

        }
3
  • I think 1st call of SaveChanges somehow refreshes the changeTracker and even though I change the EntityState to Deleted, it ignore this. But I don't know how to take care of this even if I am correct. Commented Oct 11, 2013 at 8:09
  • I'm sure you have good reason to do it...but an update before a delete to me seems pointless? Commented Oct 11, 2013 at 8:16
  • Well, it is somehow due the current design of Auditing the entity changes. And if I do not update first, I can't get the username who deleted the record. Commented Oct 11, 2013 at 8:21

1 Answer 1

1

I think you are being fooled by the lazy nature of LINQ here.

The sequence you create here:

var entitiesMarkedAsDelete = ChangeTracker.Entries<FooEntity>()
                             .Where(e => e.State==EntityState.Deleted);

.. is being evaluated each time it is being iterated, so the second time you foreach over it, you don't actually get any results back, since there are no entities in the deleted state anymore.

So to fix this, you simply have to pipe the sequence into fx. a list, by calling .ToList on it:

var entitiesMarkedAsDelete = ChangeTracker.Entries<FooEntity>()
                             .Where(e => e.State==EntityState.Deleted).ToList();

That way both foreach statements will iterate over the same entities, and they should be deleted properly.

Sign up to request clarification or add additional context in comments.

4 Comments

Peter this helped what I wanted to achieve. In the 1st SaveChanges, it commits and in the 2nd one it deletes. But I think they are not done within a transaction at all so if the DELETE fails, the UPDATE won't be rolled back. Right?
Yeah, the way it works now the two calls are 2 different transactions, so it wont roll the updates back. But you should be able to combine them in one transaction. Here is some info
Last thing: Do you think it would make sense to include also the .Detached states?
Hmm, no can't really see why that would make any sense :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.