如何清理Entity Framework對像上下文?

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

如果某些文檔通過了驗證而一個文檔失敗,則所有通過驗證的文檔仍會添加到對像上下文中。我必須清理對像上下文,因為它可能會被重用,並且可能發生以下情況。

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()將拋出異常。

所以我必須在驗證錯誤的情況下刪除所有已添加的文檔。我當然可以先執行驗證,只在成功驗證後才添加所有文檔,但遺憾的是這並沒有解決整個問題 - 如果SaveChanges()失敗,所有文檔仍然保持添加但未保存。

我試圖分離返回的所有對象

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

但我得到一個例外,說明該對像沒有附加。那麼如何擺脫所有已添加但未保存的對象?

一般承認的答案

這只是一個微不足道的錯誤,但我將在這裡留下問題 - 也許它會幫助其他人。

我有以下內容

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

而且看不到它。


熱門答案

Daniel的回答對我有用,但是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;
            }
        }
    }


Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因