在之前的專案中,我們遇到了一個情境,在需要處理多個非同步操作,例如多個網絡請求或文件處理時,需要設定一個總和的超時時間,當超過這個時間時,只回傳成功執行的非同步操作結果,並放棄還沒做完的部分。這篇文章會說明如何應對這種特殊需求。
在非同步情境下使用 ConcurrentDictionary
在處理非同步操作時,當多個非同步任務同時操作共享資源時,可能會導致資料不一致。這篇文章將聚焦於如何在非同步情境下使用 ConcurrentDictionary
取代 Dictionary
來解決這些問題。
資料查詢很慢的原因與因應方式
在實際專案中,資料查詢緩慢是一個常見的問題,如何找出具體原因成了一個很重要的主題。但在工作中,很多人往往過於注重單一面向而沒有精確的找出真正的瓶頸。例如,因為 ORM 使用不當而導致效能低落,卻將問題歸咎於 ORM 本身進而禁用 ORM。直接撰寫 SQL 查詢雖然可能較快,但失去了 ORM 的優勢。如果能先意識到 ORM 使用不當的問題並加以改善,或許能同時達到效能需求並保有 ORM 的優勢。
找到問題後的解決方案又是另一個複雜的過程,本文將簡單記錄幾個排查資料查詢緩慢的常見方向及應對方式。
Entity Framework Core 預熱
在使用 Entity Framework Core (EF Core) 進行資料存取操作時,初次查詢時會有耗時較長的現象。這種延遲主要是因為 EF Core 在第一次執行查詢時需要進行一系列的初始化步驟。這些步驟造成的延遲可能會對效能敏感的應用程式造成不利的影響。例如在 WebAPI 服務中,如果初始化花費太多時間可能造成連線超時。而且在效能監測時,這種初始化所造成的延遲可能會產生極端的執行時間資料影響到效能的解讀。
為了解決這個問題,通常會在應用程式啟動階段加入一些預熱的操作,以提前完成一些必要的初始化步驟。這篇文章會介紹兩種預熱解法,要注意的是這兩個解法不是針對所有的初始化步驟,目的只是要達到觸發 DbContext.OnModelCreating()
的效果來降低首次查詢的延遲時間。
責任鏈模式 - Fluent 風格
一般範例中的責任鏈,負責組合各實作的 Handler 時通常會如下方這樣組合,這樣的做法不管從操作上還是閱讀上都比較不友善:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// Init
IHandler positiveEven = new PositiveEvenHandler();
IHandler negativeEven = new NegativeEvenHandler();
IHandler positiveOdd = new PositiveOddHandler();
IHandler negativeOdd = new NegativeOddHandler();
// Configure
positiveEven.SetNext(negativeEven);
negativeEven.SetNext(positiveOdd);
positiveOdd.SetNext(negativeOdd);
// Call the chain
positiveEven.Handle(1);
positiveEven.Handle(-1);
positiveEven.Handle(2);
positiveEven.Handle(-2);
這篇主要是紀錄透過簡單的修改讓 Handler 能更簡單的組合責任鏈。
C# 語言特性更新 - C# 7
C# 各版本新特性摘要,包含自己的想法與實務上的偏好。
C# 7 系列比較特殊,總共經過 7.0、7.1、7.2、7.3 四個版本,且範圍有高度重疊,所以這邊不分開看,直接依照 2021 年版官方整合過的文件將 C# 7 的新特性一起看。
可重用的 XML 文件註解
在 EF Core 中自定義 ValueConverter
關於 EF Core 中的值轉換 (Value Conversion),官方文件已經展示的非常詳細,但這樣的實作使得值轉換和 DbContext
高度相依,在中小型專案中這樣已經足夠,但在複雜的產品群中,如果需要基於 EF Core 建立內部共用的套件,就會難以將這些客製化的 ValueConverter
從套件中抽離,也難以讓應用程式自行擴充自己特殊的 ValueConverter
,本文主要提供另外一個面向的實作來達到更低的耦合度與更高的可擴充性。