分享我們專案中基於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