EF Core - Transaction
🐧關於 Transaction在系統開發中,最可怕的狀況不是資料存不進去,而是「資料只成功了一半」。
你可能會覺得沒什麼——多一筆少一筆資料,好像影響不大。但實際上,這種「半成品」的狀態,才是造成系統錯誤與災難的根源。
使用者下單成功了,庫存卻沒扣 → 超賣
客戶付款完成,但系統沒記帳 → 客訴、查帳風暴
發票開出來了,卻沒連到訂單 → 財報對不起來
這些問題不是 bug,也不是 crash,而是資料邏輯不一致,讓系統表面正常、實際混亂。這時候,就需要一種「全部成功或全部失敗」的保護機制 —— 這就是 交易(Transaction) 的存在價值。
交易就像你畫圖時的一顆橡皮擦:如果中間畫錯了,可以整張擦掉重來,而不是留下殘破不堪的塗鴉。
Using Transactions
🌊 SaveChanges() 自動包成 Transaction在 EF Core 中,只要你呼叫 SaveChanges() 或 SaveChangesAsync(),它就會自動包一個隱含的交易(Implicit Transaction)。這代表:
1234567using (var cont ...
Dependency Injection - 註冊、注入
有一天,我夢見我死了。
地獄門口,閻羅王拿出一本厚厚的註冊清單,一邊唸:「根據你的 ServiceCollection,這輩子你註冊了以下幾項依賴…」
12345678IConfidenceService → FakeItTillYouMakeItServiceILoveService → UnhealthyAttachmentServiceILogger<YourLife> → Mom'sConstantNaggingICareerPlanner → JustFollowWhatEveryoneElseDidServiceISelfWorthEvaluator → DependsOnLikesAndRetweetsServiceIPurposeOfLifeResolver → null
我試圖抗議:「等等!我沒有註冊這些啊!」閻羅王翻了翻後台的 StackTrace,淡淡地說:「人走著走著、就註冊成這樣了。」
「每一次討好別人,你就呼叫了 ...
Dependency Injection - 生命週期
穿過茂密的樹影與輕柔的晨霧,你走進了一座靜謐的森林。
那裡沒有 bug,沒有 exception,只有陽光灑落的參天樹、木製窗框散出香氣的小屋
你打開門,進入了一間森林旅宿。櫃檯小姐微笑地遞給你一張房卡,你今晚的房間已經準備好了。
對旅宿而言,房間是 Singleton 生命週期的服務,從你入住前到離開後,它始終如一地在那裡 —— 只建一次,長存不變
你看著桌上放著一組乾淨的 Scoped 盥洗用品:牙刷、毛巾、小瓶洗髮精。它們會陪你走完這段住宿時光,使用多少、如何使用,全由你決定。但當你退房時,它們也會一起離開,下一位旅人會拿到全新的組合。
角落還放著衛生紙,柔軟、乾淨,隨時可以撕下一張來使用。你不會重複用它,也不會留著它,只會在需要的時候取一張。這,就是 Transient:臨時、即用即丟、毫無記憶的存在。
不同的服務有不同的生命週期,就像不同的物品有不同的使用方式 —— 如果錯把盥洗用品作為 Singleton 使用,那麼下一位旅客來到時,拿到的可能就是使用過得噁心牙刷。
設計生命週期的本質,不是為了節省資源,而是為了讓每一段旅程,都能乾淨、清晰、可控地發生。請進吧,旅人。我們即 ...
Dependency Injection - 靜態與依賴
今天到全聯購買了一個體重計,標籤上面寫著 static,售價 500 元。我心想:「不錯,夠便宜,看起來也夠簡單,剛好放在家門口踩一下就知道我今天有沒有胖。」回家之後,我站上去,顯示 66.6kg。
我不滿意。
我開始對著體重計自言自語:
「欸欸,我昨天吃太鹹啦,應該有水腫,不能算胖吧?」「還有,最近氣壓很低,影響感測精度你懂嗎?」「而且我最近壓力比較大可能會影響賀爾蒙,體脂肪是不是也該調整一下?」
我認真思考了一下,決定用 Dependency Injection 改造這台體重機。我開始設計以下注入內容:
IDietHistoryAnalyzer:幫我判斷昨天晚餐的影響,還會取得目前的健康最新趨勢分析
IPressureSensingService:計算壓力變動
IWeatherSensorProvider:拉取最新的氣壓與濕度資料
還打算加個 IMoodService,畢竟心情不好看起來也會比較腫,我把所有服務都準備好了,轉頭對體重機說:
「接下來,你要根據這些注入的資料來動態回傳我的理想體重。」
體重機沉默了幾秒,然後…… 它還是顯示了 66.6kg。不只沒變,它還開始 ...
Dependency Injection,不是控制,而是放手
森林的深處,有一間小木屋。每當霧氣升起,樹葉發出細碎的聲響,動物們會緩緩走進這裡 —— 這裡不熱鬧,卻總是剛剛好。
一隻老貓躺在椅上,望著壁爐裡跳動的火光,輕輕說:「我們啊,無法事事都靠自己。」這裡的每一份溫暖,都不是自己製造的,而是來自彼此的信任與協作。柴火是兔子帶來的,窗簾是松鼠縫的,茶是隔壁小鹿泡的。屋子本身沒有準備這一切 —— 但正因為如此,它才如此輕盈。
我們不在類別中自行建構一切,也不強求自己了解每個細節。我們只需要設計出一個能被好好照顧的容器,然後放手交給外界來注入所需的一切。
🪵 怎麼理解 DI你都怎麼叫同事?
👨💻 RD:欸 PO📊 PO:怎樣 RD?
看起來好像有點冷淡,對吧?彼此之間只用職稱互稱,完全不知道對方是誰、是高是矮、是圓的扁的。但這其實就蘊含了 Dependency Injection 的精髓:
他們之間的互動,是依賴「抽象(角色)」,而不是「具體(人名)」
PO 並不在乎對面的 RD 是哪個腦殘,他只關心有能當 RD 的人,誰來都行,只要符合這個職責就好。這就是所謂的依賴抽象(依賴介面),而不是綁定具體對象。
🪵 李氏替換 ...
錯誤防暴網設計 2 - 優惠券
夜晚是多麼美好的事物呀!她張開雙臂,把整個世界,所有悲喜擁入懷中,沉默著傾聽萬物的低喃、嘆息、抱怨或喜訊。我多半時間都是歡迎她的,特別是在一天奔波後,滿身疲憊、挫折與委屈彷彿蘇軾《臨江仙》中的遊子,渴望遠離塵世喧囂,到一個毫無紛亂之地,過著簡單平安的一生。
然而,每當靜夜離去,我卻也不得不承認 —— 昨夜的自己,只是又一次在苦中找尋出口罷了。系統亦然。每一次錯誤的發生,也許令人焦躁,但若能妥善處理、柔和回應,就能讓使用者感受到:「啊,原來這個系統,是有被好好照顧過的。」
🧱 規劃我們定義的 GlobalExceptionHandler
UseExceptionHandler 是什麼?當你開發一個 ASP.NET Core 應用時,難免會碰上各式各樣的例外(Exception),這時候,如果每個地方都用 try-catch 包起來,不但重複、難維護,還容易漏掉。ASP.NET Core 為此提供了一個現成的機制:app.UseExceptionHandler(…),讓你能夠集中處理應用程式中的所有錯誤。
根據官方文件, 例外處理器 Lambda 函數,這個方法可以讓你註冊一條錯 ...
你說你 200,但我知道你快崩潰了
夜已深,桌上的燈還亮著。你坐在螢幕前,滑著那些 commit 記錄,畫面一行一行閃爍著變更的痕跡。世界安靜下來時,反而讓人開始聽見自己的內心。
那是一段日子,你明明撐得很辛苦,卻還是對朋友說:「我很好。」就像有的 API,明明出錯了,卻還是包裝成一個 200 OK。你開始意識到,有些錯誤不是程式的錯,而是我們不願意讓人知道「其實我現在沒那麼好」。但 API 和人都一樣。你不說,別人只會以為你真的沒事。錯了,就該勇敢說出口。這不只是對外部的交代,更是對自己的一種體貼。
🧳 RESTful 派的觀點:讓 HTTP status 說話WebAPI 出錯時,是否必須透過 HTTP Status 反映執行結果,例如:找不到時吐 404、系統出錯時回應 500?
在這個 API 世界裡,RESTful 就像是遵守交通號誌的好市民:綠燈行,紅燈停,該錯就錯,該成功就成功,乾淨俐落。
🎯 HTTP Status 是最基本的語言禮儀RESTful 設計精神強調:HTTP Status Code 本來就是用來傳達狀態的。
2xx:成功(200 OK、201 Created)
4xx:客戶 ...
金流中介者之 Exception 防暴網設計
💵 站台建立的目的這是一個專門串接多家第三方金流的站台,前台可以依照情況切換不同金流提供者。整個站台的角色是「金流中介者」,幫助前台整合各家金流流程。
在這樣的架構下,例外處理(Exception Handling)變得非常關鍵。因為錯誤不僅可能來自系統內部,也可能是來自外部金流系統的 timeout、錯誤參數或伺服器無回應等狀況。
因此,我們使用 ExceptionHandlerMiddleware 來當作 API 的防爆層(Fallback Layer),讓:
內部開發者能清楚知道發生什麼錯
外部串接方只看到簡單明確的錯誤資訊
這樣能確保資訊安全,同時提升除錯效率。
💵 Global ExceptionMiddleware設計的重點:
捕捉所有未處理的 Exception
記錄 Log
給用戶一種統一格式的 JSON 回應
在 Debug 模式下額外附上 StackTrace
實作參考
1234567891011121314151617181920212223242526272829303132333435363738394041424344 public ...
讓他代我做:Delegate 應用實踐
在 第一篇
我們從「什麼是委派(Delegate)」開始,理解它的誕生是為了解決什麼樣的需求:將行為作為參數傳遞。
接著第二篇
我們進一步探討了實務上會遇到的挑戰,以及 .NET 框架提供的標準解法(像是泛型委派 Action、Func、Predicate)。
這次,我們要來真正動手,體會 Delegate 如何在日常開發中,帶來更高的彈性與更好的設計感。
🏪 動態選擇條件總結訂單資訊💬說明
你有一組訂單資料 Order,客戶希望可以動態選擇條件,例如:
只加總金額超過 500 的訂單
只加總客戶名稱是 “Allen” 的訂單
加總指定客戶清單裡的人(比如 VIP 客戶)
請設計一個方法,讓使用者自訂篩選條件(以委派的方式傳入),然後針對符合條件的訂單做加總。
解析
先定義甚麼是 Order
123456789101112public class Order{ public int Id { get; set; } public string OrderId { get; set; } public string Cust ...
讓他代我做:Delegate 從使用到設計,為目的而進化
在人生的旅途中,有些行動,不是為了此刻,而是為了將來某個尚未到來的時刻,悄悄種下伏筆。
就像在一場重要的典禮上,你輕聲叮囑朋友:「等我上台尻校長的光頭時,幫我拍一張照片。」你清楚地設定了做什麼,但並沒有干涉朋友用哪台相機、站在哪個角度,只是信任對方,讓他自由捕捉那個瞬間。
又像叫了一份外送,你指定了:「請把三商巧福送到我家門口。」你決定了目標,但至於外送員選擇騎機車、開車,走哪條路線抵達,則完全交給他靈活安排。
你無需親手掌控每一個細節,只需種下清楚的意圖,並信任交付
這種「指定意圖,委託執行」的方式,在程式設計的世界裡的 Delegate
在上一篇中,我們認識了 Delegate 的基本結構與意義;而這一篇,我們將走得更深,去感受它在現實設計中如何展現靈活的力量,又如何結合泛型,成為更強大而多變的工具;更會看見它化身為 Action、Func、Predicate,滲透進每一段程式邏輯之中。
從重複中提煉靈活:泛型的智慧設計在開發過程中,我們遇過這種情況:
12345public delegate int ...