Entity Framework中的連接管理

来源:http://www.cnblogs.com/from1991/archive/2016/04/23/5425018.html
-Advertisement-
Play Games

EF框架對資料庫的連接提供了一系列的預設行為,通常情況下不需要我們太多的關註。但是,這種封裝,降低了靈活性,有時我們需要對資料庫連接加以控制。 EF提供了兩種方案控制資料庫連接: 傳遞到Context的連接; Database.Connnection.Open(); 下麵詳解。 傳遞到Context ...


EF框架對資料庫的連接提供了一系列的預設行為,通常情況下不需要我們太多的關註。但是,這種封裝,降低了靈活性,有時我們需要對資料庫連接加以控制。

EF提供了兩種方案控制資料庫連接:

  • 傳遞到Context的連接;
  • Database.Connnection.Open();

下麵詳解。

傳遞到Context的連接

EF6之前版本

有兩個接受Connection的構造方法:

public DbContext(DbConnection existingConnection, bool contextOwnsConnection) 
public DbContext(DbConnection existingConnection, DbCompiledModel model, bool contextOwnsConnection)

使用上面兩個方法的時候需要註意的限制:
1、如果使用上面任意一個方法,傳遞了一個已經打開的連接,則會在首次使用EF操作資料庫時拋出一個InvalidOperationException異常,表示不能重覆打開一個鏈接;

2、contextOwnsConnection參數指示在DbContext對象Dispose時候是否Dispose底層的資料庫連接。無論參數是否設置,在DbContext.Dispose()時都會關閉底層的Connection。所以,如果你有超過一個DbContext使用同一連接,其中任何一個DbContext對象Dispose時都會關閉該連接(類似的,如果你將ADO.NET 和DbContext對象混合使用,在DbContect對象Dispose時也會關閉連接)。

可以通過傳遞一個關閉的連接,在創建的上下文中僅打開一次連接,且僅執行代碼繞過上面第一條限制。如下:

 1 using System.Collections.Generic; 
 2 using System.Data.Common; 
 3 using System.Data.Entity; 
 4 using System.Data.Entity.Infrastructure; 
 5 using System.Data.EntityClient; 
 6 using System.Linq; 
 7  
 8 namespace ConnectionManagementExamples 
 9 { 
10     class ConnectionManagementExampleEF5 
11     {         
12         public static void TwoDbContextsOneConnection() 
13         { 
14             using (var context1 = new BloggingContext()) 
15             { 
16                 var conn = 
17                     ((EntityConnection)  
18                         ((IObjectContextAdapter)context1).ObjectContext.Connection)  
19                             .StoreConnection; 
20  
21                 using (var context2 = new BloggingContext(conn, contextOwnsConnection: false)) 
22                 { 
23                     context2.Database.ExecuteSqlCommand( 
24                         @"UPDATE Blogs SET Rating = 5" + 
25                         " WHERE Name LIKE '%Entity Framework%'"); 
26  
27                     var query = context1.Posts.Where(p => p.Blog.Rating > 5); 
28                     foreach (var post in query) 
29                     { 
30                         post.Title += "[Cool Blog]"; 
31                     } 
32                     context1.SaveChanges(); 
33                 } 
34             } 
35         } 
36     } 
37 }

第二個限制僅僅意味著你要確保確實要關閉連接後再調用DbContext.Dispose()。

EF6版本及更新版本

EF6和將來的版本的DbContext有兩個與以往版本相同重載的構造方法,但是不在要求傳遞一個關閉的連接了。所以下麵代碼在EF6及以後版本是正確的:

 1 using System.Collections.Generic; 
 2 using System.Data.Entity; 
 3 using System.Data.SqlClient; 
 4 using System.Linq; 
 5 using System.Transactions; 
 6  
 7 namespace ConnectionManagementExamples 
 8 { 
 9     class ConnectionManagementExample 
10     { 
11         public static void PassingAnOpenConnection() 
12         { 
13             using (var conn = new SqlConnection("{connectionString}")) 
14             { 
15                 conn.Open(); 
16  
17                 var sqlCommand = new SqlCommand(); 
18                 sqlCommand.Connection = conn; 
19                 sqlCommand.CommandText = 
20                     @"UPDATE Blogs SET Rating = 5" + 
21                      " WHERE Name LIKE '%Entity Framework%'"; 
22                 sqlCommand.ExecuteNonQuery(); 
23  
24                 using (var context = new BloggingContext(conn, contextOwnsConnection: false)) 
25                 { 
26                     var query = context.Posts.Where(p => p.Blog.Rating > 5); 
27                     foreach (var post in query) 
28                     { 
29                         post.Title += "[Cool Blog]"; 
30                     } 
31                     context.SaveChanges(); 
32                 } 
33  
34                 var sqlCommand2 = new SqlCommand(); 
35                 sqlCommand2.Connection = conn; 
36                 sqlCommand2.CommandText = 
37                     @"UPDATE Blogs SET Rating = 7" + 
38                      " WHERE Name LIKE '%Entity Framework Rocks%'"; 
39                 sqlCommand2.ExecuteNonQuery(); 
40             } 
41         } 
42     } 
43 }

      還有,現在contextOwnsConnection參數決定是否要在DbContext對象Dispose時關閉並Dispose連接對象。因此,上面代碼,在DbContext對象Dispose時,資料庫並未關閉(32行),但在以前的版本在此處會關閉連接。上面代碼會在第40行關閉並釋放。
       當然,如果你仍然可以讓DbContext對象控制連接,把contextOwnsConnection設置為true,或者使用另一個構造方法。

Database.Connnection.Open()

EF6以前的版本

EF5及之前版本ObjectionContext.Connection.State狀態更新存在BUG,該值不能正確反映底層連接的狀態。例如執行下麵代碼,獲取的狀態為Closed,即使其底層確實為Open:

((IObjectContextAdapter)context).ObjectContext.Connection.State

      另外,如果你通過調用Database.Connection.Open()打開資料庫連接,資料庫連接將一直打開,直到執行下次執行一個查詢或者任何請求連接的操作(例如SaveChanges)。但是在此之後底層連接將會被關閉。那麼Context將會因任意的資料庫操作而重新打開連接併在之後重新關閉:

 1 using System; 
 2 using System.Data; 
 3 using System.Data.Entity; 
 4 using System.Data.Entity.Infrastructure; 
 5 using System.Data.EntityClient; 
 6  
 7 namespace ConnectionManagementExamples 
 8 { 
 9     public class DatabaseOpenConnectionBehaviorEF5 
10     { 
11         public static void DatabaseOpenConnectionBehavior() 
12         { 
13             using (var context = new BloggingContext()) 
14             { 
15                 // At this point the underlying store connection is closed 
16  
17                 context.Database.Connection.Open(); 
18  
19                 // Now the underlying store connection is open  
20                 // (though ObjectContext.Connection.State will report closed) 
21  
22                 var blog = new Blog { /* Blog’s properties */ }; 
23                 context.Blogs.Add(blog); 
24                  
25                 // The underlying store connection is still open  
26  
27                 context.SaveChanges(); 
28  
29                 // After SaveChanges() the underlying store connection is closed  
30                 // Each SaveChanges() / query etc now opens and immediately closes 
31                 // the underlying store connection 
32  
33                 blog = new Blog { /* Blog’s properties */ }; 
34                 context.Blogs.Add(blog); 
35                 context.SaveChanges(); 
36             } 
37         } 
38     } 
39 }

 

EF6及將來版本

       在EF6和將來的版本中,框架採用的方案是如果代碼通過context.Database.Connection.Open()打開一個資料庫連接,有理由相信代碼想要自己控制連接的打開和關閉,框架將不再自動關閉連接。

       註意:這一特性可能造成資料庫連接長時間打開,所以要特別留意,防止連接未及時關閉。

       EF6中修複了ObjectContext.Connection.State狀態更新的BUG。

 1 using System; 
 2 using System.Data; 
 3 using System.Data.Entity; 
 4 using System.Data.Entity.Core.EntityClient; 
 5 using System.Data.Entity.Infrastructure; 
 6  
 7 namespace ConnectionManagementExamples 
 8 { 
 9     internal class DatabaseOpenConnectionBehaviorEF6 
10     { 
11         public static void DatabaseOpenConnectionBehavior() 
12         { 
13             using (var context = new BloggingContext()) 
14             { 
15                 // At this point the underlying store connection is closed 
16  
17                 context.Database.Connection.Open(); 
18  
19                 // Now the underlying store connection is open and the 
20                 // ObjectContext.Connection.State correctly reports open too 
21                  
22                 var blog = new Blog { /* Blog’s properties */ }; 
23                 context.Blogs.Add(blog); 
24                 context.SaveChanges(); 
25  
26                 // The underlying store connection remains open for the next operation  
27                     
28                 blog = new Blog { /* Blog’s properties */ }; 
29                 context.Blogs.Add(blog); 
30                 context.SaveChanges(); 
31  
32                 // The underlying store connection is still open 
33   
34            } // The context is disposed – so now the underlying store connection is closed 
35         } 
36     } 
37 }

 


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

-Advertisement-
Play Games
更多相關文章
  • Debian系統的普通用戶需要安裝軟體時,往往會收到“Permission denied”的提示,這時候需要root許可權。那麼如何在不登陸超級管理員賬戶的前提下擁有root許可權呢?對於大多數Linux系統來說,我們可以通過“sudo”命令來獲取root許可權,或者通過“su”登陸超級管理員賬戶來進行各 ...
  • C#泛型是一種高復用性、安全和高效的技術,通過類型參數可以將參數的聲明、實現推遲到客戶代碼中。但是這種延遲卻降低了類型參數在泛型定義中的可操作性。例如資源釋放。 但是如果T實現了IDisposable介面,則上面代碼可能存在資源泄露的風險。但是由於不知道T是否實現了IDisposable介面,所以不 ...
  • 菜鳥要飛系列目錄 1.(菜鳥要飛系列)一,基於Asp.Net MVC5的後臺管理系統(前言) 2.(菜鳥要飛系列)二,基於Asp.Net MVC5的後臺管理系統(實現登陸功能) 3.(菜鳥要飛系列)三,基於Asp.Net MVC5的後臺管理系統(用戶的增刪改查功能) 4.(菜鳥要飛系列)四,基於As ...
  • 最近由於伺服器變更為Linux系統.MsSql for Linux什麼時候出來到生產環境使用還是要很長時間的.於是考慮使用Mysql資料庫,ORM使用EF.於是先踩下坑順便記錄一下,有需要的tx可以參考下.當你考慮使用EF連接Mysql的時候肯定是已經在網上搜了一堆教程.網上教程基本都是使用控制台做 ...
  • 現在在Windows下的應用程式開發,VS.Net占據了絕大多數的份額。因此很多以前搞VC++開發的人都轉向用更強大的VS.Net。在這種情況下,有很多開發人員就面臨瞭如何在C#中使用C++開發好的類的問題。下麵就用一個完整的實例來詳細說明怎樣用托管C++封裝一個C++類以提供給C#使用。 比如,現 ...
  • EF6開始提供了通過async和await關鍵字實現非同步查詢和保存的支持(.net 4.5及更高版本)。雖然不是所有的操作都能從非同步中獲益,但是耗時的操作、網路或IO密集型任務中,使用非同步可以提升客戶端性能和增強伺服器的擴展性。 本文將覆蓋一下主題: 實例演練非同步操作 創建模型 創建同步程式 改為異 ...
  • 所有需要賬戶登錄的website 基本都會想到這樣一個問題, 如何保持用戶在一定時間內登錄有效。 最近本人就在項目中遇到這樣的需求,某些頁面只能Admin賬戶登錄後訪問, 當登錄Admin賬戶後如何才能保持登錄信息呢? 用Cookie或者Session來保存登錄信息已經是一種比較成熟的技術。但是對於 ...
  • 1.這裡僅對web控制項而言,onclick事件執行的是客戶端中的代碼, 可以把事件寫在html頁面上,也可以放在調用的js文件中(此處為A.js)。 A.js: 運行結果: 2.onserverclick事件,這個是執行服務端的方法。 對應的在後臺補充相應的事件: 執行結果: 註意,當onclick ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...