I am adding several entities to an object context.
try { forach (var document in documents) { this.Validate(document); // May throw a ValidationException. this.objectContext.AddToDocuments(document); } this.objectContext.SaveChanges(); } catch { // How to clean-up the object context here? throw; }
If some of the documents pass the the validation and one fails, all documents that passed the validation remain added to the object context. I have to clean-up the object context because it may be reused and the following can happen.
var documentA = new Document { Id = 1, Data = "ValidData" }; var documentB = new Document { Id = 2, Data = "InvalidData" }; var documentC = new Document { Id = 3, Data = "ValidData" }; try { // Adding document B will cause a ValidationException but only // after document A is added to the object context. this.DocumentStore.AddDocuments(new[] { documentA, documentB, documentC }); } catch (ValidationException) { } // Try again without the invalid document B. This causes an exception because // of a duplicate primary key - document A with id 1 is added a second time. this.DocumentStore.AddDocuments(new[] { documentA, documentC });
This will again add document A to the object context and in consequence SaveChanges()
will throw an exception because of a duplicate primary key.
So I have to remove all already added documents in the case of an validation error. I could of course perform the validation first and only add all documents after they have been successfully validated but sadly this does not solve the whole problem - if SaveChanges()
fails, all documents still remain added but unsaved.
I tried to detach all objects returned by
this.objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added)
but I am getting a exception stating that the object is not attached. So how do I get rid of all added but unsaved objects?
DbContext. Remove Method (Microsoft.
Deleting an entity is done using the Remove or RemoveRange method of the DbSet. Alternatively, you can also set the entity state as Deleted . We can delete records either in connected or disconnected Scenarios. We will also look at how to remove multiple records from the database using the RemoveRange method.
The approach that you adopt to deleting entities via the DbContext depends on whether the context is currently tracking the entity being deleted or not. In the following example, the entity to be deleted is obtained by the context, so the context begins tracking it immediately.
The best way to refresh entities in your context is to dispose your context and create a new one.
Daniel's answer worked for me, however the EntityFramework API is different in version 6+. Here is a method I added to my custom repository container that will detach all entities from the DbContext's ChangeTracker:
/// <summary> /// Detaches all of the DbEntityEntry objects that have been added to the ChangeTracker. /// </summary> public void DetachAll() { foreach (DbEntityEntry dbEntityEntry in this.Context.ChangeTracker.Entries().ToArray()) { if (dbEntityEntry.Entity != null) { dbEntityEntry.State = EntityState.Detached; } } }
It was just a trivial bug but I am going to leave the question here - maybe it helps others.
I had the following
var objectStateEntries = this.objectContext .ObjectStateManager .GetObjectStateEntries(EntityState.Added); foreach (var objectStateEntry in objectStateEntries) { this.objectContext.Detach(objectStateEntry); }
while I wanted the following
foreach (var objectStateEntry in objectStateEntries) { this.objectContext.Detach(objectStateEntry.Entity); }
and couldn't see it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With