0

I have a method that creates a new entity with a pretty complex object graph that may or may not contain existing entities in it. That method manages its own context. It returns the entity which is consumed in a method on a different class that maintains its own context and attempts to add the entity.

The reason for the division of labor is because the second method does a bunch of processing that is common to several different entity creation scenarios. I don't want to save the entity in the first method, because it's important that the second method is successful before saving the entity to the database.

The problem is that when the second context adds the entity, it is treating the entire object graph as brand new and is creating duplicates in the database.

What is the best way to add the entity to the second context and have all of the existing entities in its object graph just get attached?

I'm trying to avoid doing something like traversing the object graph and testing for IDs > 0...

lintmouse
  • 5,079
  • 8
  • 38
  • 54
  • If your "bunch of processing" fails just don't call `SaveChanges` and nothing gets written to the DB. Can't you do that? When you dispose the first context and try to save the object graph in a new context you have lost all the information about entity states you had supplied to the first context. You are expecting EF to look into a crystal ball if you don't want to restore all the entity state info again. There is no magic available. Either hard work again in the second context or try to avoid two contexts, preferably the latter solution. – Slauma May 05 '13 at 16:46
  • Originally I used one context and passed it between methods. But then I changed it so the first method can be run in parallel. So I didn't want to pass around a context since it isn't thread safe. With regards to your first point, when you say 'don't call SaveChanges', do you mean after calling it in the first method? I want it to be an all-or-nothing deal. – lintmouse May 05 '13 at 19:03
  • You could wrap the two `SaveChanges` calls into a `TransactionScope`. The changes that have been sent to the DB by the two `SaveChanges` would only be actually written into the DB when the scope is committed. Otherwise both will be rolled back. – Slauma May 05 '13 at 20:03
  • How does it keep track of what contexts are part of the scope? Do I have to do a pessimistic save and then AcceptChanges after the TransactionScope completes? – lintmouse May 11 '13 at 04:27
  • I don't think that the `TransactionScope` has any knowledge of what a context is. Creating an instance of a scope starts a transaction on database level. Committing or disposing it ends the transaction. Every database command issued by `SaveChanges` (no matter which context) is part of that outer transaction. But good question about calling `AcceptChanges`. I'm not sure about the correct way. If you dispose the contexts after the scope anyway, if something failed or not, you can probably use a default `SaveChanges` that accepts at once. – Slauma May 11 '13 at 10:27

0 Answers0