.net entity - 實體框架和連接池




framework connection (5)

下面的代碼幫助我的對象刷新了新的數據庫值。 Entry(object).Reload()命令強制對象調用數據庫值

GM_MEMBERS member = DatabaseObjectContext.GM_MEMBERS.FirstOrDefault(p => p.Username == username && p.ApplicationName == this.ApplicationName);
DatabaseObjectContext.Entry(member).Reload();

我最近開始在我的.NET 4.0應用程序中使用Entity Framework 4.0,並對與池相關的一些事情感到好奇。

  1. 據我所知,連接池由ADO.NET數據提供者管理,在我的情況下是MS SQL服務器。 這是否適用於實例化新實體上下文( ObjectContext )時,即無參數的new MyDatabaseModelEntities()

  2. a)為應用程序創建全局實體上下文(即一個靜態實例)或b)為每個給定的操作/方法創建和展示一個實體上下文,並使用一個using塊,有哪些優缺點?

  3. 任何其他建議,最佳實踐或對於某些應該了解的情景的常見方法?


符合EF6(4,5也)文檔: https://msdn.microsoft.com/en-us/data/hh949853#9 ://msdn.microsoft.com/en-us/data/hh949853#9

9.3每個請求的上下文

實體框架的上下文旨在用作短期實例,以提供最佳的性能體驗 。 預計上下文會被短暫丟棄,並且因此被實現為非常輕量級的,並且盡可能地重新利用元數據。 在Web場景中,記住這一點非常重要,並且不得超過單個請求的持續時間。 同樣,在非Web場景中,根​​據您對實體框架中不同級別的緩存的理解,上下文應該丟棄。 一般來說,應該避免在應用程序的整個生命週期中有一個上下文實例,以及每個線程和靜態上下文的上下文。


據丹尼爾西蒙斯說:

在每個服務方法的Using語句中創建一個新的ObjectContext實例,以便在方法返回之前處理它。 這一步對於您的服務的可擴展性至關重要。 它確保數據庫連接不會在服務調用中保持打開狀態,並且特定操作使用的臨時狀態在操作結束時會被垃圾收集。 實體框架會自動緩存它在應用程序域中所需的元數據和其他信息,並且ADO.NET可以池化數據庫連接,因此每次重新創建上下文都是快速操作。

這是來自他的全面文章:

http://msdn.microsoft.com/en-us/magazine/ee335715.aspx

我相信這個建議可以擴展到HTTP請求,所以對ASP.NET有效。 有狀態的胖客戶端應用程序(如WPF應用程序)可能是“共享”上下文的唯一情況。


  1. 連接池的處理與其他ADO.NET應用程序一樣。 實體連接仍然使用與傳統連接字符串的傳統數據庫連接。 我相信你可以關閉連接字符串中的連接池,如果你不想使用它。 (閱讀有關SQL Server連接池(ADO.NET)的更多信息)
  2. 永遠不要使用全局上下文。 ObjectContext內部實現了幾種模式,包括標識映射和工作單元。 使用全局上下文的影響因應用程序類型而異。
  3. 對於Web應用程序,請求使用單個上下文。 對於Web服務,每次調用使用單個上下文。 在WinForms或WPF應用程序中,每個表單或每個演示者使用單個上下文。 可能有一些特殊的要求不允許使用這種方法,但在大多數情況下,這已經足夠了。

如果您想知道WPF / WinForm應用程序的單個對像上下文有什麼影響,請查看article 。 這是關於NHibernate會話,但想法是一樣的。

編輯:

在使用EF時,默認情況下每個實體僅為每個上下文加載一次。 第一個查詢創建實體實例並將其存儲在內部。 後續任何需要具有相同鍵的實體的查詢才會返回此存儲的實例。 如果數據存儲中的值發生更改,您仍然收到來自初始查詢的值的實體。 這被稱為標識映射模式 。 您可以強制對像上下文重新加載實體,但它會重新加載單個共享實例。

在對上下文調用SaveChanges之前,對實體所做的任何更改都不會持久。 您可以在多個實體中進行更改並一次存儲它們。 這被稱為工作單元模式 。 你不能有選擇地說出你想保存哪個修改的附加實體。

結合這兩種模式,你會看到一些有趣的效果。 整個應用程序只有一個實體實例。 即使變更尚未持續(提交),實體的任何更改都會影響整個應用程序。 在大多數情況下,這不是你想要的。 假設你在WPF應用程序中有一個編輯表單。 您正在與實體合作,並且您決定取消複雜的編輯(更改值,添加相關實體,刪除其他相關實體等)。 但實體已在共享上下文中進行了修改。 你會怎麼做? 提示:我不知道ObjectContext上的任何CancelChanges或UndoChanges。

我認為我們不必討論服務器場景。 在多個HTTP請求或Web服務調用之間簡單共享單個實體會使您的應用程序無用。 任何請求都可以觸發SaveChanges並從其他請求中保存部分數據,因為您在所有請求之間共享單個工作單元。 這也會帶來另一個問題 - 上下文和上下文中實體的任何操作或上下文使用的數據庫連接都不是線程安全的。

即使對於只讀應用程序,全局上下文也不是一個好的選擇,因為每次查詢應用程序時都可能需要新數據。


這些都不適合我。 我在另一個問題中找到了解決方案。 我會在這裡添加它以便於參考:

你需要做一個引用,所以它會被複製到應用程序的路徑中。 因為稍後它將在運行時被引用。 所以你不需要復制任何文件。

private volatile Type _dependency;

public MyClass()
{
    _dependency = typeof(System.Data.Entity.SqlServer.SqlProviderServices);
}




.net database entity-framework ado.net connection-pooling