1. 程式人生 > >分享我們專案中基於EF事務機制的架構

分享我們專案中基於EF事務機制的架構

寫在前面:

1. 本文中單元測試用到的資料庫,在執行測試之前,會被清空,即使用空資料庫。

2. 本文中的單元測試都是正確通過的。

要理解EF的事務機制,首先要理解這2個類:TransactionScope和DbContext。

DbContext是我們的資料庫,通常我們會建一個類MyProjectDbContext繼承自DbContext,裡面包含所有的資料庫表。這個類相當於定義了一個完整的資料庫。

下面通過一些單元測試來看看這2個類是如何工作的。

 1 [Test]
 2 public void Can_Rollback_On_Errors_In_Different_Context()
3 { 4 var user1 = Mock.Users.Random(); 5 var user2 = Mock.Users.Random(); 6 user2.FirstName = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; 7 var userCount = 0; 8 try 9 { 10 using (var scope = new TransactionScope()) 11 { 12 using
(var db = new MyProjectDbContext()) 13 { 14 db.Users.Add(user1); 15 db.SaveChanges(); 16 userCount = db.Users.Count(); 17 } 18 using (var db = new MyProjectDbContext()) 19 { 20 db.Users.Add(user2);
21 db.SaveChanges();//will throw exception 22 } 23 scope.Complete(); 24 } 25 } 26 catch(Exception) 27 { 28 29 } 30 Assert.AreEqual(1, userCount); 31 using (var db = new MyProjectDbContext()) 32 { 33 Assert.AreEqual(0, db.Users.Count()); 34 } 35 }

注意第一個assert,userCount是等於1的,也就是說第一個db.SaveChanges()是順利執行了的。但是看看第二個assert,資料庫裡面卻沒有user記錄。這就是使用TransactionScope得到的真正的事務機制。

再看一個測試:

 1 [Test]
 2 public void Cannot_Rollback_Without_Scope()
 3 {
 4     var user1 = Mock.Users.Random();
 5     var user2 = Mock.Users.Random();
 6     user2.FirstName = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
 7     var userCount = 0;
 8     try
 9     {
10         using (var db = new MyProjectDbContext())
11         {
12             db.Users.Add(user1);
13             db.SaveChanges();
14             userCount = db.Users.Count();
15         }
16         using (var db = new MyProjectDbContext())
17         {
18             db.Users.Add(user2);
19             db.SaveChanges();//will throw exception
20         }
21     }
22     catch (Exception)
23     {
24 
25     }
26     Assert.AreEqual(1, userCount);
27     using (var db = new MyProjectDbContext())
28     {
29         Assert.AreEqual(1, db.Users.Count());
30     }
31 }

這個測試跟上面的測試差不多,唯一的區別就是沒有使用TransactionScope把兩個DbContext包起來。於是每個DbContext成為獨立的事務。

再來看一個測試:

 1 [Test]
 2 public void Shouldnot_SaveToDB_As_ScopeNotComitted()
 3 {
 4     var user1 = Mock.Users.Random();
 5     var userCount = 0;
 6     try
 7     {
 8         using (var scope = new TransactionScope())
 9         {
10             using (var db = new MyProjectDbContext())
11             {
12                 db.Users.Add(user1);
13                 db.SaveChanges();
14                 userCount = db.Users.Count();
15             }
16             //scope.Complete();
17         }
18     }
19     catch (Exception)
20     {
21 
22     }
23     Assert.AreEqual(1, userCount);
24     using (var db = new MyProjectDbContext())
25     {
26         Assert.AreEqual(0, db.Users.Count());
27     }
28 }

}

這個測試表明,一旦DbContext被TransactionScope包起來之後,那麼scope必須要呼叫scope.Complete()才能將資料更新到資料庫。

基於上面的這些知識,我們可以很容易為EF搭建支援真正事務的框架。下面我簡單介紹下我們的專案架構(EF CodeFirst, MVC)。

基於EF事務機制的架構

Domain層:

定義資料實體類,即資料庫中的表。定義繼承自DbContext的MyProjectDbContext。

Service層:

主要用於封裝所有對資料庫的訪問。例子程式碼如下:

1 public List<User> GetAllUsers()
2 {
3     using (var db = new MyProjectDbContext())
4     {
5         return db.Users.ToList();
6     }
7 }

上面這段程式碼中注意要使用using,否則DbContext的延遲載入功能會在controller層被呼叫。加了using之後,可以避免在controller層對資料庫的直接訪問。

Controller層:

呼叫service層的程式碼從資料庫中得到資料,返回給UI。例子:

1 public ActionResult GetAllUsers()
2 {
3     var users = IoC.GetService<IUserService>().GetAll();
4     return View(users);
5 }

同時將UI傳回來的資料更新到資料庫,這時如果需要呼叫多個service來更新資料庫,那麼就需要用到事務。例子:

 1 public ActionResult DeleteUser(int userId)
 2 {
 3     try
 4     {
 5         using (var scope = new TransactionScope())
 6         {
 7             IoC.GetService<IUserService>().DeleteLogs(userId);
 8             IoC.GetService<IUserService>().DeleteUser(userId);
 9             scope.Complete();
10             return View();
11         }
12     }
13     catch(Exception)
14     {
15         
16     }
17     return View();
18 }

通常情況下,我們會在MyControllerBase裡面加一個 ActionResult TryScope(Action action)的方法,這樣在子類裡面就可以不用寫try-catch了。

對於EF更深層的機制,我瞭解的也不多。歡迎大家討論!

相關推薦

分享我們專案基於EF事務機制架構

寫在前面: 1. 本文中單元測試用到的資料庫,在執行測試之前,會被清空,即使用空資料庫。 2. 本文中的單元測試都是正確通過的。 要理解EF的事務機制,首先要理解這2個類:TransactionScope和DbContext。 DbContext是我們的資料庫,通常我們會建一個類MyProjectDb

mysql是我們專案非常常用的資料型資料庫。但是因為我們需要在資料庫儲存中文字元,所以經常遇到資料庫亂碼情況。下面就來介紹一下如何徹底解決資料庫中文亂碼情況。

mysql是我們專案中非常常用的資料型資料庫。但是因為我們需要在資料庫儲存中文字元,所以經常遇到資料庫亂碼情況。下面就來介紹一下如何徹底解決資料庫中文亂碼情況。 1、中文亂碼 1.1、中文亂碼 create table user(name varchar(11)); # 建立user表

ImageNet專案基於CNN的各種神經網路結構演進過程

1、ImageNet資料集背景介紹: 如果說Mnist資料集將初學者領進了深度學習領域,那麼Imagenet資料集在深度學習中尤其是計算機視覺領域掀起了巨大的浪潮。ImageNet專案於2007年由斯坦福大學華人教授李飛飛創辦,目標是收集大量帶有標註資訊的圖片資料供計算機視

分享個Duilib基於wke的瀏覽器控制元件

概述 wke是基於谷歌chrome瀏覽器原始碼的裁剪版本,大小僅僅只有10M左右,無需依賴其他的擴充套件庫(跟CEF的一大堆大約40M的DLL來比簡直爽呆了),就可以在本地使用谷歌核心快速載入網頁。網上也有基於wke在Duilib 上擴充套件的控制元件程式碼,其

Golang自玩專案一個重連機制實現.

package tcp_listen type Connection interface { Read() (value interface{}, tag byte, err error)

webservice之cxf實現[web專案基於maven與spring整合]

webservice現開發的已實現元件不少,使用過的就有xfire及cxf. cxc基於maven與spring整合過程如下: STEP 1. 依賴包新增 在pom.xml檔案的標籤中增加如下(版本號依個人需要調整): <depende

abp web.mvc專案的選單載入機制

# abp中的選單載入機制 在abp中選單的定義與我們傳統寫的框架不一樣,它是在編寫程式碼的時候配置,而我們一般寫的通用許可權管理系統中,是後期在後臺介面中新增的。這一點有很大不同。abp關於選單的定義及管理挺複雜的。 ## 與選單相關的結構類、介面及擴充套件方法類 + MenuDefinition:定義

在Blazor Server 專案使用 EF Core Sqlite

按照教程建立了一個 Blazor Server 專案 教程地址: https://docs.microsoft.com/zh-cn/aspnet/core/tutorials/build-a-blazor-app?view=aspnetcore-5.0 還有一個教程是:https://ww

第四課:通過配置文件獲取對象(Spring框架的IOC和DI的底層就是基於這樣的機制

ted const dex generate stat clas name 必須 nbsp 首先在D盤創建一個文件hero.txt,內容為:com.hero.Hero(此處必須是Hero的完整路徑) 接下來是Hero類 package com.hero; publi

知物由學 | 基於DNN的人臉識別的反欺騙機制

ctu 打印 mage eas 系統 分類 傳遞 實時 技術分享 “知物由學”是網易雲易盾打造的一個品牌欄目,詞語出自漢·王充《論衡·實知》。人,能力有高下之分,學習才知道事物的道理,而後才有智慧,不去求問就不會知道。“知物由學”希望通過一篇篇技術幹貨、趨勢解讀、人物思考和

EF Core 2.0開啟Transaction事務會對DbContext創建和關閉數據庫連接的行為有所影響

dup .net core compute har sin locks png 技術分享 dbcontext 我們先在數據庫中建立一個Book表: CREATE TABLE [dbo].[Book]( [ID] [int] IDENTITY(1,1) NOT

25、【支付模組開發】——將配置好的支付寶沙箱環境整合到我們專案以及支付介面的編寫

####1、將支付寶Demo中的相關檔案複製到我們的專案中: 首先,我們將Demo中src中的包及裡面的檔案複製到我們專案中 同樣,我們也要講zhifubao.properties這個配置檔案方法我們專案中的 resources目錄下: 加下來就是我們的jar包了~ 首先我們先在

微服務基於Spring Boot的maven分散式專案框架的搭建

專案介紹 在微服務架構中,傳統的 maven 專案已經無法滿足,開始走向分散式架構,本專案主要搭建一個空的 maven 分散式架構,可以運用到實際專案中進行擴充套件,可以在文末獲取原始碼和更多資源。 這裡搭建的是基於 maven 的分散式工程,因為在一個專案中,多個微服務是屬於同

【slighttpd】基於lighttpd架構的Server專案實戰(8)—狀態機機制回顧

轉載地址:https://blog.csdn.net/jiange_zh/article/details/50640270 有限狀態機FSM(Finite State Machine) 關於狀態機的一個極度確切的描述是它是一個有向圖形,由一組節點和一組相應的轉移函式組成。狀態機通過響應一系列

在SSM專案使用AOP管理事務的配置教程

今天來記錄一下在SSM專案中經常使用到的事務管理的配置,其實在spring中事務管理有很多方法,但今天我用的是最簡單的這種(還不是因為懶~)aop自動管理事務。 1.首先我們需要有一個整合好的SSM框架專案,具體搭建步驟可以參考我的另一篇文章:最新版的SSM框架spring5.0搭建教程&nb

Spring --15.Spring基於xml的宣告事務控制

開發環境: jdk1.8 Idea 2017 :Maven工程、引入父工程 Tomcat:apache-tomcat-8 Spring:5.0.7 一、事務控制 1、概述 事務的概念: 事務是邏輯上一組操作、組成這組操作各個邏輯單元、要麼一起成功、要麼一起失敗。 事

基於MFC的實時視覺化專案檢視重新整理訊息的嚴謹使用

        在實時可視專案中,檢視的實時重新整理顯示對軟體的體驗感來說非常重要,當演算法的效率達到實時,比如一秒40幀,如果實時顯示幀率更不上,則體驗感將大大折扣,讓使用者感覺你的演算法並沒有40幀,當然最關鍵的是解決顯示的效率問題。  

針對SpringBoot專案的引數傳遞使用RSA加密機制保證安全性進行封裝成工具

spring-boot-starter-security 1 概述 針對SpringBoot專案中的引數傳遞使用RSA加密機制保證安全性進行封裝成工具,實現自動加密返回資料、解密傳入資料並對映成json 2 使用  這裡的使用就比較簡單了。 (1)將工具匯入專案中。 (

專案實際開發遇到的事務問題

廢話不多說 看功能: 最近做了一個app的記步功能,要求是app一開啟就開始進行步數的計算,然後一分鐘向後臺傳送一次資料儲存到資料庫中,此時儲存的是使用者的走的步數和有效步數(有效步數是在一分鐘內步頻大於90的算是真正的走路)和有效時間,然後當你開啟記步頁面的時候,又一個請求一分鐘一次

專案常用的JavaScript Array(陣列) 物件方法(我是基於Vue2+iView的專案

1、JavaScript splice() 方法 splice() 方法用於新增或刪除陣列中的元素。 注意:這種方法會改變原始陣列,所有主要瀏覽器都支援splice()。 let imgArrItem = [ "/images/201812