簡體   English   中英

是否需要處置實體框架上下文對象

[英]Is Disposing of Entity Framework context object required

我們在WCF服務方法中使用實體框架與數據庫進行通信,最近我們在服務代碼上運行代碼審查工具。 像往常一樣,我們通過工具獲得了許多審核提案,許多評論意見建議處置實體框架上下文對象。 所以,我的問題是,如果我在方法中使用實體框架上下文對象,一旦我退出該方法,GC不會清理上下文對象? 我們需要顯式處理上下文對象嗎?

簡單地說: DbContext實現了IDisposable ,因此您應該在完成后立即手動處理它。

不需要處理它,因為GC最終會收集它,但GC不是確定性的:你永遠不知道什么時候會“最終”。 在它被處理之前,它將保留未使用的資源 - 例如,它可能仍然具有開放的數據庫連接。 除非您手動處理, 否則在GC運行之前不會釋放這些資源。 根據具體細節,您可能會發現您不必要地阻止了網絡資源,文件訪問,並且您肯定會保留比您需要的更多內存。

還有一個潛在的打擊:當你手動處理一個對象時,GC通常不需要在該對象上調用Finalizer(如果有的話)。 如果讓GC自動處理帶有Finalizer的對象,它會將對象放在Finalizer Queue中 - 並自動將對象提升到下一代GC生成。 這意味着具有終結器的對象將始終以比GCed之前所需的數量級更長的數量級掛起(因為不太頻繁地收集連續的GC生成)。 DBContext可能屬於此類別,因為底層數據庫連接將是非托管代碼。

(有用的參考 。)

我認為最好的方法是在using語句中對其進行編碼

using(var cx = new DbContext())
{
  //your stuff here
}

所以它得到了自動處理

一般來說,如果某些東西實現了IDisposable ,那么當你通過時,明確處理它是一個好主意(TM)。 如果您不擁有所述對象的實現,則尤其如此; 在這種情況下,你應該把它當作一個黑盒子。 另外,即使現在不一定“需要”處理它,它可能在將來。

因此,恕我直言,你是否“需要”明確處置該對象的問題是無關緊要的。 如果要求處置 - 由於實施IDisposable - 它應該被處置。

建議使用DBContext的方法是根本不處理它(在大多數情況下它是規則的例外),即使它是一次性對象。

問題的一個例子,第一個例子是在using語句中進行調用並對其進行評估,而第二個例子是在之后對其進行評估。 (第一個ons運行,第二個拋出錯誤The operation cannot be completed because the DbContext has been disposed.

List<Test> listT;
using (Model1 db = new Model1())
{
    listT = db.Tests.ToList(); //ToList Evaluates
}
foreach (var a in listT)
{
    Console.WriteLine(a.value);
}

IEnumerable<Test> listT1;
using (Model1 db = new Model1())
{
    listT1 = db.Tests;
}
foreach (var a in listT1) //foreach evaluates (but at wrong time)
{
    Console.WriteLine(a.value);
}

同樣的問題發生在

IEnumerable<Test> listT1;
Model1 db = new Model1();
listT1 = db.Tests;
db.Dispose();
foreach (var a in listT1) //foreach evaluates (but at wrong time)
{
    Console.WriteLine(a.value);
}

只要您不手動打開連接,只需使用即可安全使用

IEnumerable<Test> listT1;
Model1 db = new Model1();
listT1 = db.Tests;
foreach (var a in listT1) //foreach evaluates (but at wrong time)
{
    Console.WriteLine(a.value);
}

永遠不要處置。 因為它會在大多數情況下照顧好自己,就像它設計的那樣。

現在,如果您通過強制打開連接,則上下文不會在傳輸完成時自動關閉它,因為它不知道何時然后您必須/應該/應該處置該對象或關閉連接並保持對象未公開。

額外的午夜閱讀:

  1. http://blog.jongallant.com/2012/10/do-i-have-to-call-dispose-on-dbcontext.html#.U6WdzrGEeTw
  2. https://msdn.microsoft.com/en-us/data/jj729737.aspx

無需顯式處置DbContext。

這是來自前DbContext工具的舊版本。 DbContext是托管代碼,並且樂觀地維護數據庫連接。 為什么大錘呢? 什么時候趕時間? 為什么不讓垃圾收集器決定在機器空閑或需要內存時清理的最佳時間? 另請參閱這篇文章: https//blog.jongallant.com/2012/10/do-i-have-to-call-dispose-on-dbcontext/

不必擔心必須處理將簡化和優化您的代碼。 通常我可以從數據庫“helper”類繼承到我使用getter返回已經存在的DbContext實例或實例化新實例的地方。

public class DataTools
{
    private AppContext _context;
    protected AppContext Context => _context ?? (_context = new AppContext());
}

pubic class YourApp : DataTools
{
    public void DoLotsOfThings()
    {
        var = Context.SomeTable.Where(s => s.....);
        var stuff = GetSomeThing();
       foreach(){}
    }

    Public string GetSomething()
    {
        return Context.AnotherTable.First(s => s....).Value;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM