最近在研究Dapper Source Code想要抽離一些部分封裝自己想要的SQLHelper
做一些簡單筆記整理分享給版友,假如有不足的地方也期待版友留言、討論
使用建議
原因效能快,QueryFirstOrDefault跟Query的效率比較參考,兩者在測試比較是87.80 us比94.05 us。
connection.Query("select * from T").FirstOrDefault();
connection.Query("select top 1 * from T");
改為
connection.QueryFirstOrDefault("select top 1 * from T");
至於要如何手寫一個Dapper QueryFirstOrDefault核心Core
我寫一個簡化版本(不實現Mapping)給讀者參考:
有幾個重點
CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow
行為,這意思是告訴資料庫請按順序給我第一列資料就好
,這是提高效率關鍵單次read
讀取第一行資料資料,並使用空動作while把資料流快速讀完
(可以參考底下詳細說明)using System.Data;
using System.Data.Common;
public static class DapperDemo
{
public static T QueryFirstOrDefault<T>(this IDbConnection connection,string sql,Func<IDataRecord,T> selector)
{
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = sql;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult | CommandBehavior.SingleRow))
{
var data = (reader.Read() && reader.FieldCount != 0) ? selector(reader) : default(T);
while (reader.Read()) { }
while (reader.NextResult()) { }
return data;
}
}
}
}
最後做測試Demo
void Main()
{
using(var conn = Connection){
conn.Open();
//Test Data
var cmd = conn.CreateCommand();
cmd.CommandText = "with cte as ( select '0001' id,'ITWeiHan' name union all select '0002' id,'Henry' name ) select * into #T from cte ;";
cmd.ExecuteNonQuery();
//Query
var result = conn.QueryFirstOrDefault("select top 1 * from #T", reader => new {id=reader.GetString(0),name=reader.GetString(1)});
}
}
資料流沒有讀完就 return,會發生什麼事情?
可以參考Dapper作者回應的ISSUE: Issue #1210 · StackExchange/Dapper
主要避免忽略錯誤,像是在DataReader提早關閉情況,並且前面已經跟系統強調行為是單列資料(CommandBehavior.SingleRow,CommandBehavior.SingleResult),所以不會增加多少成本。
跟S.O的DataReader底層介紹 c# - How DataReader works? - Stack Overflow
弱弱的問一下,資料流沒有讀完就 return
,會發生什麼事情?
這是一個好問題
我這邊反編譯來查看Read方法但底層的call看不到
真的好神奇,期待答案。
米歐 底下更新Dapper作者的回應
暐翰
作者回真快
看很多套件作者不是不回
就是他自己也解決不了
真的 用心秒回作者 :D
原來是避免忽略錯誤的部分!又學到一點實務上不太會需要的知識XD
米歐
我覺得倒是不會
現在很多開發者都只會學怎麼用
很多概念根本不了解
導致大家寫出來的都差不多
而沒辦法寫出自己的東西
Homura
哈哈,可能彼此了解不多,這句話讓你誤會了。
我喜歡去鑽這種問題,也才會在這邊留言。
我覺得這內容很有幫助,但實務上真的很難碰到XD
主要避免忽略錯誤,像是在DataReader提早關閉錯誤情況
好奇,這在什麼情況下會發生?
好問題 我想想怎麼模擬