如何清理entity framework对象上下文?

我将几个实体添加到对象上下文中。

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; } 

如果某些文档通过了validation,而其中一个文档通过validation,则所有通过validation的文档都会添加到对象上下文中。 我必须清理对象上下文,因为它可能被重用,并且可能发生以下情况。

 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 }); 

这将再次将文档A添加到对象上下文中,结果SaveChanges()将因为重复的主键而引发exception。

所以在validation错误的情况下,我必须删除所有已经添加的文档。 我当然可以执行validation,只有在成功validation后才添加所有文档,但是不幸的是,这并不能解决整个问题 – 如果SaveChanges()失败,所有文档仍然保持添加但未保存。

我试图分离所有返回的对象

  this.objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added) 

但我得到一个exception,说明对象没有连接。 那么如何摆脱所有添加但未保存的对象呢?

这只是一个微不足道的错误,但我将在这里留下问题 – 也许这有助于其他人。

我有以下

 var objectStateEntries = this.objectContext .ObjectStateManager .GetObjectStateEntries(EntityState.Added); foreach (var objectStateEntry in objectStateEntries) { this.objectContext.Detach(objectStateEntry); } 

而我想要以下

 foreach (var objectStateEntry in objectStateEntries) { this.objectContext.Detach(objectStateEntry.Entity); } 

并不能看到它。

丹尼尔的答案为我工作,但是EntityFramework API在版本6+是不同的。 这是我添加到我的自定义存储库容器,将从DbContext的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()) { if (dbEntityEntry.Entity != null) { dbEntityEntry.State = EntityState.Detached; } } } 

晚会有点晚,但你有没有考虑过工作单元模式?

简而言之,它可以让你有一个交易,然后你可以回滚(处置)或提交(保存更改)

注意:这是事务,如同在一个操作中的变化分组,而不是在一个SQL BEGIN TRAN。 这一切仍然由SaveChanges()方法处理。

就像是:

 Public Class UnitOfWork Implements IUnitOfWork Implements IDisposable Private ReadOnly Property ObjectContext As Interfaces.IObjectContext Public Sub New(ByVal objectContext As Interfaces.IObjectContext) _objectContext = objectContext End Sub Public Sub Dispose() Implements IDisposable.Dispose If _objectContext IsNot Nothing Then _objectContext.Dispose() End If GC.SuppressFinalize(Me) End Sub Public Sub Commit() Implements IUnitOfWork.Commit _objectContext.SaveChanges() End Sub End Class 

每当你创build一个工作单元时,它都需要一个对象上下文 – 我们使用Unity来生成这些工具,这样如果旧工具被处置

对于那些使用Entity Framework Core 1.0 RC2 +的人 ,我更新了Garrys的答案。

参考

 using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.ChangeTracking; 

更新的代码

  /// <summary> /// Detaches all of the EntityEntry objects that have been added to the ChangeTracker. /// </summary> public void DetachAll() { foreach (EntityEntry entityEntry in this.Context.ChangeTracker.Entries().ToArray()) { if (entityEntry.Entity != null) { entityEntry.State = EntityState.Detached; } } } 
 var entries = ((DbContext)ef).ChangeTracker.Entries(); foreach (var entry in entries) { entry.State = System.Data.EntityState.Detached; }