EF Core - 交易的界線
迷航實驗開航前:DBContext 的布陣實驗一:TransactionScope 實測雙 DbContext 同一資料庫實驗二:TransactionScope 跨資料庫實驗三:BeginTransaction() 建出來的交易只能用在建立它的那條 connection 上實驗四:BeginTransaction + 共用連線summary「啊…我有開 TransactionScopeAsyncFlowOption.Enabled 嗎?」「咦?這兩個 Context 是不是不同連線?」「等一下,我是不是跨資料庫了?那 MSDTC 呢?」
交易的邊界,就像洋流與領海,有時你以為你還在安全區,其實早已飄出防線。
這篇筆記,就是一趟從這場 Bug 航行而來的實驗紀錄 —— 我們用四種實際情境來測試 EF Core 的交易能力:
同資料庫、不同 DbContext
跨資料庫
共用連線 vs 不共用連線
TransactionScope vs BeginTransaction
如果你也曾在交易邊界迷航過,歡迎登船
為了這趟「交易航線實驗」,我們準備了三個 DbContext:
Adven ...
Dapper vs EF Core
如果資料存取是場人生選擇,那 EF Core 就像「全包式旅行團」:行李、住宿、行程幫你安排好,你只要準時上車;而 Dapper 則像「背包客自由行」:想去哪、怎麼走、要不要迷路,全靠你自己。
在 .NET 的世界裡,EF Core 與 Dapper 是資料存取的兩大門派,一個幫你包辦大小事,一個讓你操控每一行 SQL。
你可能常常陷入這種掙扎:
「欸現在這隻微服務要查一堆訂單、明細、客戶資料,我要不要用 EF?還是會變龜速大怪獸?」「有三層關聯欸,用 Dapper 要手動 map 到哭出來,欄位一多手都斷了吧…」
🌊 ORM
在開發應用程式時,資料通常儲存在資料庫(Database)中,而程式則是用物件(Object)在操作資料。但是資料庫與程式是兩種世界
資料庫用的是「表格」(table)來存資料,C# 用的是「物件」和「類別」
這兩個東西的結構不同、語言不同、邏輯也不同。
👉 ORM(Object-Relational Mapping)本質是什麼?
它是一座橋梁,幫你自動把「資料表」轉成「物件」,也幫你把你操作的物件轉回資料表格式,這個過程就叫做 ...
EF Core - DbContext 生命週期
blow outEF Core 的預設生命週期:ScopedScoped vs Transient:生命週期的差異為何 using dbContext()EF 會幫我們打理連線嗎?summary
「這裡的風很大,請小心 DbContext 被吹出作用域。」
開發 ASP.NET Core 應用程式時,你一定碰過這段設定
1services.AddDbContext<MyDbContext>();
這一行註冊你的 DbContext,但你知道它的 生命週期(Lifetime)是什麼嗎?Scoped、Transient 差在哪?又該怎麼選擇?今天我們就來一趟資料庫生命週期的航行
Entity Framework contexts
By default, Entity Framework contexts are added to the service container using the scoped lifetime because web app database operations are normally scoped to the client req ...
EF Core - Transaction
Using Transactions
關於 TransactionSaveChanges() 自動包成 Transaction使用 BeginTransaction() 控制交易範圍,可以包多次 SaveChanges()多個 DbContext 共用同一個交易使用 TransactionScope 自動處理多資源交易SaveChanges() 測試BeginTransaction() 測試TransactionScope 測試summary在系統開發中,最可怕的狀況不是資料存不進去,而是「資料只成功了一半」
你可能會覺得沒什麼——多一筆少一筆資料,好像影響不大。但實際上,這種「半成品」的狀態,才是造成系統錯誤與災難的根源
使用者下單成功了,庫存卻沒扣 → 超賣
客戶付款完成,但系統沒記帳 → 客訴、查帳風暴
發票開出來了,卻沒連到訂單 → 財報對不起來
這些問題不是 bug,也不是 crash,而是資料邏輯不一致,讓系統表面正常、實際混亂。這時候,就需要一種「全部成功或全部失敗」的保護機制 —— 這就是 交易(Transaction) 的存在價值。
交易就像你畫圖時的一顆橡皮擦 ...
Dependency Injection - EF Core DbContext
Constructor injection behavior
Dependency Injection - 測試
測試to Feng,這篇介紹 Autofac 觀念的文章 https://blog.darkthread.net/blog/autofac-notes-1/ ,有舉了一個範例,在完全不修改主要程式的情況下抽換不同功能的元件。如果要做單元測試,這超級重要。
例如:某個依賴 WebApi 提供內容的函式,單元測試期間需模擬不同 WebAPI 傳回結果,此時可透過 DI 將 WebAPI 服務元抽換成假元件傳回特定值以驗證不同狀況下邏輯正確。範例:https://blog.darkthread.net/blog/aspnet-core-di-practice/
86 不存在的戰區 - 請為自己努力活過而感到驕傲
前言人在前進時,時常懷疑自我價值在挫折之中,容易陷入內心的拉扯與消耗彷彿眼前的陰影遮蔽了過往一路走來的堅持與努力曾經一步一腳印走過的路,如今竟變得模糊不清。
蕾娜曾對辛耶說過
想要戰鬥到底、想要活到最後,現在才能在這裡
我想,你可以更為此感到驕傲
故事大綱故事以戰火連天的前線作為開場,硝煙瀰漫、砲火轟鳴,大火照亮了那群平均年齡不到 20 歲的年輕士兵臉龐。然而,真正令人不寒而慄的,並非戰場本身,而是那冰冷無情且毫無人性的聲音,他透過通訊設備,不斷以侮辱與命令鞭策著這群尚未成年便踏入戰場的孩子…
就在我們尚未從戰爭的殘酷中回神,鏡頭一轉,卻進入另外一個不同的世界 – 溫柔清晨的陽光灑落在潔白的床連與床鋪上,共和國的居民在柔軟的被窩中悠悠醒來,伴隨著古典音樂的樂聲享用早餐,一切顯得如此安詳、那麼的理所當然、前線與後方之間的鴻溝,在這一瞬間顯得如此殘酷而荒謬
這不正是現實的倒影嗎?一場冠冕堂皇之下,悄然 ...
Pagination
照著進度走的人生OFFSET / FETCH程式端 VS Stored ProcedureOFFSET 實現分頁的效能問題「鍵值分頁(Keyset Pagination)」優化Keyset Pagination 真的是「萬能解法」嗎如果資料在分頁期間被新增或刪除,OFFSET 與 Keyset 哪個更安全summary世界是一整本書,人生可以被清楚地切成第 1 頁、第 2 頁、第 50 頁,我只要照著頁碼翻,就一定能看到我該看到的那一段,像是 30 歲要做到第 30 頁、35 歲要結婚、40 歲要買房,同齡人u3已經在地第 20 頁,我怎麼還在第 15 頁?
因為你的人生座標來自「別人在哪一頁」,這就是 OFFSET FETCH!
感覺 OFFSET 規規矩矩的,一頁頁走應該沒甚麼問題,然而,OFFSET 有一個隱藏陷阱!
世界不是靜止的書,有人中途離場(刪資料)、有人突然插隊(新增資料),頁碼可能看起來沒有錯,但那一頁的內容已經變了,明明我照順序走,卻發現自己重複經歷同樣的痛苦,又或者莫名其妙的錯過了一些重要的東西,OFFSET 的人生,會迷失在比較與對齊之中。也不是說 OFFSE ...
取得系統資訊
Process.GetProcesses() 範圍並不限於應用程式本身,它會返回系統中所有正在執行的 Process 資訊,這包括其他應用程式、系統服務以及其他使用者的 Process,但具體可見的範圍可能受到權限的限制。
WorkingSet64 是 Process 的實際記憶體使用量(物理記憶體),數值為 bytes。
Lambda Expression 應用 - TotalMemory簡單來說就是在方法呼叫端傳入我們的條件 (像是傳入一個 Where 一樣),來決定內部的計算邏輯範圍
這個實作情境是這樣,使用 Process.GetProcesses() 取得所有 Process,並且篩選 > 20 MB 的 Process,最後計算前兩名的資訊
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354void Main(){ DisplayMemory(memory => memory > 20 * 1024 ...
LambdaExpression
Lambda Expression 應用 - 用強型別動態指定欄位名稱
🌿 Lambda 的誕生:從 Delegate 到優雅的表達式Delegate:型別安全的 Callback🌸 Expression-bodied 屬性🌸 LINQ🌸 用強型別動態指定欄位名稱在 Task.Run 放 Lambda(背景執行)在 LINQ 裡塞 async LambdaParallel.ForEachAsync(.NET 6+)搭配 async Lambda🌸 多語系主題推薦頁summaryLambda 表達式(Lambda Expression) 並不是從天而降的魔法。它的根基,其實建立在一個更早、更樸實的概念上 : delegate
所謂 Callback(回呼),是一種「把方法當作參數傳遞」的設計方式。舉個例子,假設你想在任務完成後執行一段通知程式
12345void DownloadFile(string url, Action onCompleted){ Console.WriteLine($"Downloading {url}. ...














