Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to clean-up an Entity Framework object context?

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?

like image 299
Daniel Brückner Avatar asked Mar 17 '10 21:03

Daniel Brückner


People also ask

Which method is used to let the DbContext know an entity should be deleted?

DbContext. Remove Method (Microsoft.

How do I remove data from Entity Framework?

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.

What does EF's DbContext need to be tracking in order to delete a row from the database?

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.

How do I refresh EF context?

The best way to refresh entities in your context is to dispose your context and create a new one.


2 Answers

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;             }         }     } 
like image 128
Garry English Avatar answered Sep 19 '22 21:09

Garry English


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.

like image 34
Daniel Brückner Avatar answered Sep 18 '22 21:09

Daniel Brückner