EntityFramework中的DbContext使用疑點說明

来源:http://www.cnblogs.com/ICE_Inspire/archive/2016/12/11/6159090.html
-Advertisement-
Play Games

1.DbContext怎麼在Asp.mvc中使用? 這麼定義之後,所有需要用到DbContext對象的地方,都調這個方法。 2. 不要隨便using或Dispose DbContext會導致延遲載入的不可用,還會有一些其他錯誤 如IQueryable<T> 下麵的方法(.First() /.Coun ...


1.DbContext怎麼在Asp.mvc中使用?

  public class Repository
    {
        //實例化EF容器:有弊端。一個線程里可能會創建多個DbContext
        //DbContext db = new DbContext();

        //改造:保證一個請求線程中只有一份EF容器(你要明白:一個url請求到伺服器,IIS就開一個線程去處理)
        protected DbContext GetDbContext
        {
            get
            {
                //向線程緩存中查詢,如果返回的是null,則創建,同時存入到這個線程緩存中
                //註意的是線程緩存CallContext,而不是我們熟悉的HttpRuntime.cache。意味著這個DbContext對象在這個線程內能被其他方法共用。
                object efDbContext = CallContext.GetData("DbContext");
                if (efDbContext == null)
                {
                    efDbContext = new DbContext();
                    //存入到這個線程緩存中
                    CallContext.SetData("DbContext", efDbContext);
                }
                return efDbContext as DbContext;
            }
        }
  }

  這麼定義之後,所有需要用到DbContext對象的地方,都調這個方法。

2. 不要隨便using或Dispose DbContext會導致延遲載入的不可用,還會有一些其他錯誤 如IQueryable<T> 下麵的方法(.First() /.Count())也不能用。

情況一:

  a寫法結果正確

PhoneBookEntities phoneBookEntities = new PhoneBookEntities();
var ci = phoneBookEntities.ContactInfo.FirstOrDefault();//這裡並沒有拿到ci對象裡面的GroupInfo屬性。
if (ci != null) MessageBox.Show(ci.GroupInfo.GroupName);//是延遲載入,訪問 ci.GroupInfo.GroupName 才會去資料庫查數據

  b寫法報錯

ContactInfo ci = null;
using (PhoneBookEntities phoneBookEntities = new PhoneBookEntities())
{
	ci = phoneBookEntities.ContactInfo.FirstOrDefault();
}

if (ci != null) MessageBox.Show(ci.GroupInfo.GroupName);
//報錯:此ObjectContext實例已釋放,不可再用於需要連接的操作。意味著延遲載入不可用。

情況二:

  a寫法報錯

IQueryable<ContactInfo> ci = null;
using (PhoneBookEntities phoneBookEntities = new PhoneBookEntities())
{
	ci = phoneBookEntities.ContactInfo.Where(c => true);
}

if (ci != null) MessageBox.Show(ci.Count().ToString());//報錯:提示DbContext已經釋放。

  b寫法正確

IQueryable<ContactInfo> ci = null;
using (PhoneBookEntities phoneBookEntities = new PhoneBookEntities())
{
	ci = phoneBookEntities.ContactInfo.Where(c => true);
	if (ci != null) MessageBox.Show(ci.Count().ToString());//可以返回正確結果。
}

  

3.為什麼你要using 或dispose掉DbContext ?

是擔心資料庫連接沒有釋放?還是擔心DbContext占用過多資源呢?
首先擔心資料庫連接沒有釋放肯定是多餘的,因為DbContext在SaveChanges完成後會釋放掉打開的資料庫連接。
可以反編譯一下SaveChages的源碼。
擔心DbContext占用過多資源也是多餘的,有GC回收。

結論,You can call Dispose, but in most common scenarios you don’t need to.

更詳細的可以看這個英文博客的文章,其中有 Diego Vega (the Senior SDE Lead on EF) 的回信

Hello Jon,

The default behavior of DbContext is that the underlying connection is automatically opened any time is needed and closed when it is no longer needed. E.g. when you execute a query and iterate over query results using “foreach”, the call to IEnumerable<T>.GetEnumerator() will cause the connection to be opened, and when later there are no more results available, “foreach” will take care of calling Dispose on the enumerator, which will close the connection. In a similar way, a call to DbContext.SaveChanges() will open the connection before sending changes to the database and will close it before returning.

Given this default behavior, in many real-world cases it is harmless to leave the context without disposing it and just rely on garbage collection.

That said, there are two main reason our sample code tends to always use “using” or dispose the context in some other way:

1. The default automatic open/close behavior is relatively easy to override: you can assume control of when the connection is opened and closed by manually opening the connection. Once you start doing this in some part of your code, then forgetting to dipose the context becomes harmful, because you might be leaking open connections.

2. DbContext implements IDiposable following the recommended pattern, which includes exposing a virtual protected Dispose method that derived types can override if for example the need to aggregate other unmanaged resources into the lifetime of the context.

 

By the way, with DbContext the pattern to open the connection manually and override the automatic open/close behavior is a bit awkward:

((IObjectContextAdapter)dbContext).ObjectContext.Connection.Open()

But we have a bug to make this easier as it used to be with ObjectContext before, e.g.:

dbContext.Database.Connection.Open()

Hope this helps,

Diego

附上參考博客:http://www.cnblogs.com/mecity/archive/2011/07/17/2108508.html

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、put/checkAndPut 使用checkAndPut,需要先對數據進行驗證,上面的例子中,向row1中的cf:col1寫入數據"E",而驗證的是row1中的cf:col5的值是否為"E",註意這一點,相當於加了條件。 2、使用get讀取數據 參考結果: 3、使用scan獲取數據 4、del ...
  • 工作中發現在oozie中使用sqoop與在shell中直接調度sqoop性能上有很大的差異。為了更深入的探索其中的緣由,開始了oozie的源碼分析之路。今天第一天閱讀源碼,由於沒有編譯成功,不能運行測試用例,直接使用sublime肉眼閱讀,還是挺費勁的。 雖然流程還不是順暢,但是大體上的內容還算是了 ...
  • 所有 ReSherper 的功能都可以使用快捷鍵。大部分功能都有預設快捷鍵,剩下的少數功能可以自定義快捷鍵。 ReSharper 提供了兩種快捷鍵的方式 Visual Studio:這種方式可以減少與 Visual Studio 本身快捷鍵的衝突。 ReSharper 2.0/IntelliJ ID ...
  • 網上有用的資料不多,在一本電子書中摘抄了內容如下 webControls配置節只有一個clientScriptsLocation屬性,此屬性用於指定ASP.NET客戶端腳本的預設存放路徑。這些文件是包含在HTML代碼生成的ASPX頁面時這些需要的客戶端功能,如智能導航和客戶端控制項驗證。 <webCo ...
  • 上周收到本書作者李爭送的一本12月份的新書《微軟開源跨平臺移動開發實踐》。這本書的內容確是超豐富,濃縮了微軟這三年向開源和跨平臺領域的轉變,微軟在開源和跨平臺領域構建出來的一套技術體系。 ...
  • C 中的事件還真是有點繞啊,以前用JavaScript的我,理解起來還真是廢了好大勁!剛開始還真有點想不明白為什麼這麼繞,想想和JS的區別,最後終於恍然大悟! C 中事件繞的根本原因: 1. C 的方法,它不是一個類型,它只是其它類型的成員; 2. C 是一個強類型的語言,定義方法時,它的參數必須指 ...
  • 文件的併發寫入問題,需要用到線程同步。而微軟也給進程同步提供了一些相關的類可以達到這樣的目的,本文使用到的 System.Threading.ReaderWriterLockSlim 便是其中之一,該類用於管理資源訪問的鎖定狀態,可實現多線程讀取或進行獨占式寫入訪問。利用這個類,我們就可以避免在同一... ...
  • Session 是保存用戶和 Web 應用的會話狀態的一種方法,ASP.NET Core 提供了一個用於管理會話狀態的中間件。在本文中我將會簡單介紹一下 ASP.NET Core 中的 Session 的使用方法。 安裝配置 Session 在 project.json 添加引用 Microsoft ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...