EntityFramework 事務處理

来源:http://www.cnblogs.com/yunspider/archive/2016/04/12/5384560.html
-Advertisement-
Play Games

預設情況下,當EF調用SaveChanges()時,會把生成的所有SQL命令“包”到一個“事務(transaction)”中,只要有一個數據更新操作失敗,整個事務將回滾。 在多數情況下,如果你總在數據更新操作代碼中使用一個而不是多個DbContext對象,並且只是在最後調用一次SaveChanges ...


預設情況下,當EF調用SaveChanges()時,會把生成的所有SQL命令“包”到一個“事務(transaction)”中,只要有一個數據更新操作失敗,整個事務將回滾。

在多數情況下,如果你總在數據更新操作代碼中使用一個而不是多個DbContext對象,並且只是在最後調用一次SaveChanges(),那麼EF的預設事務處理機制己經夠用了,無需做額外的事情。

然而,如果出現以下的情形,你就必須顯式地處理事務了。

第一種情況:你需要分階段地保存數據,因而需要多次調用SaveChanges()或者執行修改資料庫的SQL命令。

請看以下示例代碼:

 

using (var context = new MyDbContext())

{
    try
     {
        Person3 p = context.People3.First();

        p.Name ="newName" + (new Random().Next(1, 100));

        context.SaveChanges();

        context.Database.ExecuteSqlCommand("update Person3 setDescription={0} where Person3Id={1}",

                            "DescriptionModified at " + DateTime.Now.ToShortTimeString(),

                            p.Person3Id);
        p.age *= 2;
        context.SaveChanges();
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
     }
}

 

上述代碼中,調用兩次SaveChanges(),還有一次執行Update命令。

如果在最後一次SaveChanges()中出現異常,雖然最後一次沒成功,但你會發現前兩次數據己經保存!這就帶來了數據不一致的問題。

對於這種場景,你需要顯式地編寫事務代碼了(註:以下代碼適用於EF6):

using (var context = new MyDbContext())
 {
    using (var transaction =context.Database.BeginTransaction())
    {
        try
        {
              ……

              context.SaveChanges();

              context.Database.ExecuteSqlCommand("……);

              ……

              context.SaveChanges();
              transaction.Commit();

         }
        catch (Exception e)
        {
               Console.WriteLine(e.Message);
               transaction.Rollback();
        }
    }
}

 

特別要註意一定要調用commit(),我測試發現,只要不Commit,即使沒有異常發生,事務仍將回滾,資料庫中的數據不會更新。

第2種情況,你需要使用多個DbContext保存數據

以下是處理這種場景的典型代碼:

static void TestTransactionScope2()

{
           using (TransactionScope scope = new TransactionScope())
           {
                String connStr = ……;
                using (var conn = newSqlConnection(connStr))
                {
                    try
                    {
                        conn.Open();
                        using (var context1 =new MyDbContext(conn, contextOwnsConnection: false))
                        {
                             ……
                             context1.SaveChanges();
                        }
                      using (var context2 =new MyDbContext(conn, contextOwnsConnection: false))
                       {
                           context2.Database.ExecuteSqlCommand(……);
                           context2.SaveChanges();
                       }
                       using (var context3 =new MyDbContext2(conn, contextOwnsConnection: false))
                       {
                            ……
                            context3.SaveChanges();
                       }
                      scope.Complete();
                 }
                catch (Exception e)
                {
                       Console.WriteLine(e.ToString());
                }
                finally
                {
                        conn.Close();
                 }
            }
      }
}

 

上述代碼中有幾個關鍵點:

(1)在構造DbContext對象時,需要把一個己打開的資料庫連接對象傳給它,並且需要指定EF在DbContext對象銷毀時不關閉資料庫連接。

為實現此目的,你的DbContext對象應該類似於是這樣的,提供兩個重載的構造函數:

public class MyDbContext2 : DbContext
    {

       public MyDbContext2(DbConnection conn, boolcontextOwnsConnection):base(conn,contextOwnsConnection)
       {

       }

       public MyDbContext2():base()
       {

       }
       public DbSet<OtherEntity> OtherEntities { get; set; }

       ……
}

 

註意在代碼結束時關閉連接。

(2)如果不Commit,則所有數據將不會保存。

(3)你的電腦需要啟動MSDTC(分散式交易協調器),請先在控制面板中打開Distributed Transaction Coordinator服務,否則上述代碼將在運行時拋出MSDTC服務不可用的異常。

很明顯,當事務需要使用多個不同類型的DbContext對象時,Windows需要啟動MSDTC,這會對性能有所影響,因此在開發中應該儘量避免這種情況,如無必要,不要在單個事務中使用多個不同種類的DbContext對象。

轉自:http://blog.csdn.net/bitfan/article/details/14231561

 


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

-Advertisement-
Play Games
更多相關文章
  • 今天本想將之前的一個資料庫easy.sql用圖形化工具Navicat導入的,開始是用“運行SQL文件”導入,結果是“queries successfully”啥的,去查是否導表成功,一看並沒有。 結果失望之餘,把那個資料庫和伺服器全刪了,再建一個和要導入的資料庫同名的資料庫名,意外的是重啟後資料庫就 ...
  • 1唯一約束unique和主鍵key的區別? 1、什麼是數據的存儲引擎? 存儲引擎就是如何存儲數據、如何為存儲的數據建立索引和如何更新、查詢數據等技術的實現方法。因為在關係資料庫中數據的存儲是以表的形式存儲的,所以存儲引擎也可以稱為表類型(即存儲和操作該表的類型),在Oracle和SQL Server ...
  • 1概述 1.1 介紹 Valgrind是一套Linux下,開放源代碼(GPL V2)的模擬調試工具的集合。Valgrind由內核(core)以及基於內核的其他調試工具組成。內核類似於一個框架(framework),它模擬了一個CPU環境,並提供服務給其他工具;而其他工具則類似於插件 (plug-in ...
  • 1上下鍵讓文件為選中狀態 2左鍵選擇文件夾,再次左鍵摺疊。 ...
  • 今天,筆者在備份文件的時候,將一個word文檔從移動硬碟複製到桌面。經過一系列“復(meng)雜(bi)”的操作之後,筆者突然發現,文件無法刪除了。當右鍵文件點擊“刪除”時,出現對話框顯示“正在準備 再迴圈”的字樣。 筆者嘗試了許多方法,例如:當出現“正在準備 再迴圈”字樣時,註銷電腦;下載文件粉 ...
  • 通過上一篇的介紹我們應該對實現在ServiceProvider的總體設計有了一個大致的瞭解,但是我們刻意迴避一個重要的話題,即服務實例最終究竟是採用何種方式提供出來的。ServiceProvider最終採用何種方式提供我們所需的服務實例取決於最終選擇了怎樣的ServiceCallSite,而服務註冊 ...
  • 一、題目描述 構造程式並測試,分別是: 構造程式並測試,分別是: 1.不能觸發Fault。 2.觸發Fault,但是不能觸發Error。 3.觸發Error,但是不能產生Failure。 二、結對對象 結對對象博客: 結對照片: 貢獻比例: 三、構造程式並測試 1.不能觸發Fault. 1.1:構造 ...
  • 介面 什麼是介面? 介面代表一種能力,和抽象類類似但比抽象類的抽象程度更高! 介面的定義: 1 public interface IEat//定義一個介面 2 { 3 void Eat(string food);//為該介面定義一種能力 4 } 從上邊的例子中我們可以看到,介面中的方法是沒有方法體的 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...