關(guān)于Dapper.NET的相關(guān)論述

年少時,為何不為自己的夢想去拼搏一次呢嚎尤?縱使頭破血流荔仁,也不悔有那年少輕狂。感慨很多,最近事情也很多乏梁,博客也很少更新了次洼,畢竟每個人都需要為自己的生活去努力。

最近在一個群里遇到一個人說的話遇骑,在這里不再贅述卖毁,大概意思就是自己各種精通各種懂,面試時各種裝逼各種吊落萎,本人真誠的求教了一下他亥啦,問他是否懂這些東西的底層原理,是否了解過底層源碼练链,能否根據(jù)實際情況修改源碼翔脱,誰知被他吐槽說裝逼,說知識那么多不能什么都看源碼和理解原理吧媒鼓。但是我只想說届吁,這可是你自己說自己精通,難道精通的框架不該了解源碼和原理嗎绿鸣?難道精通就是只知道怎么簡單的應(yīng)用嗎疚沐?難道是我聊天的方式不對?

最近遇到一個問題潮模,那就是有關(guān)Dapper.NET的一些問題濒旦,Dapper.NET的效率為何很高?該組件的運行原理是什么再登?說句實話尔邓,我找了很久都沒有發(fā)現(xiàn)類似的文章,不知道是不是我的搜素方式不對锉矢,還希望發(fā)現(xiàn)類似好的文章的朋友發(fā)給我看看梯嗽,知識在于分享嘛,不要吝嗇你的知識沽损,讓我們一起進步吧灯节。

在這里簡單介紹一下其原理

一.Dapper.NET概述:

項目開發(fā)時,我們都是需要考慮項目的技術(shù)架構(gòu)绵估,尤其是對數(shù)據(jù)庫底層的考慮比較多⊙捉現(xiàn)在對于數(shù)據(jù)庫的訪問有ADO.NET,EF国裳,Dapper.NET等等形入,不同的情況會有不同的選擇,討論的時候都會說到“xx很牛逼缝左,xx效率很高”等等亿遂,總之需要干一場浓若,才算我們開過會。(很多時候蛇数,在開會前項目選什么技術(shù)早就定了挪钓,但是不開個會就顯得做事不嚴(yán)謹(jǐn)...),在選用Dapper.NET時耳舅,有人說到Dapper.NET效率高碌上,很牛逼,也不知道那個新人說了一句“為什么Dapper.NET效率高浦徊?”

好尷尬...

Dapper.NET是一個簡單的ORM馏予,專門從SQL查詢結(jié)果中快速生成對象。Dapper.Net支持執(zhí)行sql查詢并將其結(jié)果映射到強類型列表或動態(tài)對象列表辑畦。Dapper.Net緩存每個查詢的信息吗蚌。這種全面的緩存有助于從大約兩倍于LINQ到SQL的查詢生成對象。當(dāng)前緩存由兩個ConcurrentDictionary對象處理纯出,它們從不被清除宣旱。

Dapper.Net通過擴展方法將兩個映射函數(shù)添加到IDbConnection接口工育,這兩個函數(shù)都命名為ExecuteMapperQuery。第一個映射結(jié)果是一個強類型列表,而第二個映射結(jié)果是一個動態(tài)對象列表竭鞍。ExecuteMapperCommand執(zhí)行并且不返回結(jié)果集编振。所有三個方法都將參數(shù)接受為匿名類宜狐,其中屬性值映射到同名的SQL參數(shù)肛搬。

Dapper.Net旨在僅處理結(jié)果集到對象映射。它不處理對象之間的關(guān)系鸵赖,它不會自動生成任何類型的SQL查詢务漩。

二.Dapper.NET原理淺析:

通過Dapper.NET的源碼我們可以發(fā)現(xiàn)其主要是“分部方法和分部類”,有關(guān)于“分部方法和分部類”的知識可以看這篇博客:http://www.cnblogs.com/pengze0902/p/6369541.html它褪。Dapper.Net也假定連接已打開并準(zhǔn)備就緒饵骨,Dapper.NET通過對IDbConnection接口進行擴展。在Dapper.NET對數(shù)據(jù)庫連接完成后茫打,可以進行相關(guān)的操作居触,接下來我們就來看一下這些操作的實現(xiàn)方式。

1.Query()方法:

Query(thisIDbConnection cnn,stringsql,objectparam =null,

IDbTransaction transaction =null,boolbuffered =true,int? commandTimeout =null, CommandType? commandType =null

改方法表示執(zhí)行查詢老赤,返回按T輸入的數(shù)據(jù)轮洋。該方法是Query()方法的泛型方法,有7個參數(shù)抬旺,第一個參數(shù)為IDbConnection擴展類弊予,表示對IDbConnection接口進行擴展,該方法使用了可選參數(shù)嚷狞,提高方法的擴展性块促。在Query方法的實現(xiàn)中荣堰,有一個CommandDefinition類床未,用來表示sql操作的關(guān)鍵方面竭翠。在該類下有一個GetInit()方法。

2.GetInit()方法:

我們都知道Dapper.NET通過Emit反射IDataReader的序列隊列薇搁,來快速的得到和產(chǎn)生對象斋扰。GetInit()方法是一個靜態(tài)方法,該方法的“Type commandType”參數(shù)表示連接關(guān)聯(lián)的Command對象啃洋,返回一個Action委托传货。

我們就具體看一下是如何通過Emit反射IDataReader的序列隊列的。

if(SqlMapper.Link>.TryGet(commandInitCache, commandType,outaction)){returnaction; }

Link是一個泛型分部類宏娄,這是一個微緩存问裕,查看是否存在一個Action的委托。

varbindByName = GetBasicPropertySetter(commandType,"BindByName",typeof(bool));varinitialLongFetchSize = GetBasicPropertySetter(commandType,"InitialLONGFetchSize",typeof(int));

以上兩個操作主要獲取BindByName和InitialLONGFetchSize的獲取基本屬性設(shè)置孵坚。

if(bindByName !=null|| initialLongFetchSize !=null)

{varmethod =newDynamicMethod(commandType.Name +"_init",null,newType[] {typeof(IDbCommand) });varil =method.GetILGenerator();if(bindByName !=null)

{il.Emit(OpCodes.Ldarg_0);

il.Emit(OpCodes.Castclass, commandType);

il.Emit(OpCodes.Ldc_I4_1);

il.EmitCall(OpCodes.Callvirt, bindByName,null);

}if(initialLongFetchSize !=null)

{il.Emit(OpCodes.Ldarg_0);

il.Emit(OpCodes.Castclass, commandType);

il.Emit(OpCodes.Ldc_I4_M1);

il.EmitCall(OpCodes.Callvirt, initialLongFetchSize,null);

}

il.Emit(OpCodes.Ret);

action= (Action)method.CreateDelegate(typeof(Action));

}

這一步是該操作的核心部分粮宛,利用Emit反射操作。根據(jù)上一步獲取的對應(yīng)名稱的基本屬性設(shè)置卖宠,采用DynamicMethod對象巍杈,定義和表示一個可以編譯,執(zhí)行和丟棄的動態(tài)方法扛伍。丟棄的方法可用于垃圾回收筷畦。調(diào)用該對象的GetILGenerator方法,返回方法的Microsoft中間語言(MSIL)生成器刺洒,默認(rèn)的MSIL流大小為64字節(jié)鳖宾。判斷基本屬性設(shè)置不為空后,調(diào)用ILGenerator類的Emit方法逆航,Emit()將指定的指令放在指令流上鼎文,該方法接收一個IL流。EmitCall()將

call

callvirt

指令置于 Microsoft 中間語言 (MSIL) 流纸泡,以調(diào)用

varargs

方法漂问。我們看到OpCodes類,該類描述中間語言 (IL) 指令女揭。CreateDelegate()完成動態(tài)方法并創(chuàng)建一個可用于執(zhí)行它的委托蚤假。

通過以上的反射操作構(gòu)建好對象后,就會接著執(zhí)行對應(yīng)的數(shù)據(jù)庫操作吧兔。

3.QueryImpl():

privatestaticIEnumerable

QueryImpl(thisIDbConnection cnn, CommandDefinition command, Type effectiveType)

{objectparam =command.Parameters;varidentity =newIdentity(command.CommandText, command.CommandType, cnn, effectiveType, param ==null?null: param.GetType(),null);varinfo =GetCacheInfo(identity, param, command.AddToCache);

IDbCommand cmd=null;

IDataReader reader=null;boolwasClosed = cnn.State ==ConnectionState.Closed;try{

cmd=command.SetupCommand(cnn, info.ParamReader);if(wasClosed) cnn.Open();

reader= cmd.ExecuteReader(wasClosed ? CommandBehavior.CloseConnection |CommandBehavior.SequentialAccess : CommandBehavior.SequentialAccess);

wasClosed=false;vartuple =info.Deserializer;inthash =GetColumnHash(reader);if(tuple.Func ==null|| tuple.Hash !=hash)

{if(reader.FieldCount ==0)yieldbreak;

tuple= info.Deserializer =newDeserializerState(hash, GetDeserializer(effectiveType, reader,0, -1,false));if(command.AddToCache) SetQueryCache(identity, info);

}varfunc =tuple.Func;varconvertToType = Nullable.GetUnderlyingType(effectiveType) ??effectiveType;while(reader.Read())

{objectval =func(reader);if(val ==null|| valisT)

{yieldreturn(T)val;

}else{yieldreturn(T)Convert.ChangeType(val, convertToType, CultureInfo.InvariantCulture);

}

}while(reader.NextResult()) { }

reader.Dispose();

reader=null;

command.OnCompleted();

}finally{if(reader !=null)

{if(!reader.IsClosed)try{ cmd.Cancel(); }catch{/*don't spoil the existing exception*/}

reader.Dispose();

}if(wasClosed) cnn.Close();if(cmd !=null) cmd.Dispose();

}

}

該方法為執(zhí)行查詢操作的核心方法磷仰,通過CommandDefinition類的相關(guān)操作后,獲取到相應(yīng)的對象后境蔼,執(zhí)行這一步操作灶平。該方法是IDbConnection的擴展方法伺通,CommandDefinition表示sql的相關(guān)操作對象,Type表示傳入的一個有效的類型逢享。Identity對象表示Dapper中的緩存查詢的標(biāo)識罐监,該類是一個分部類,可以對其進行相應(yīng)的擴展瞒爬。GetCacheInfo()獲取緩存信息弓柱。

三.Dapper.NET擴展:

這一部分是借花獻佛,該部分代碼是對Dapper.NET代碼做一封裝侧但,可以類似于操作其他ORM的方式矢空,需要者可以自取,就不要到處去找這些東西了禀横。

Dapper.NET擴展方法包

Dapper包

四.總結(jié):

這篇博文是我硬著頭皮寫的屁药,因為基本沒有類似的文章,連參考的資料都沒有柏锄,最多的就是調(diào)用代碼的demo酿箭,對于原理和底層源碼解析基本沒有,在這里就用這篇博文引出大神對其全面的解析绢彤。希望對大家有一點幫助七问,也算是盡力了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末茫舶,一起剝皮案震驚了整個濱河市械巡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌饶氏,老刑警劉巖讥耗,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異疹启,居然都是意外死亡古程,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門喊崖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挣磨,“玉大人,你說我怎么就攤上這事荤懂∽氯梗” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵节仿,是天一觀的道長晤锥。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么矾瘾? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任女轿,我火速辦了婚禮,結(jié)果婚禮上壕翩,老公的妹妹穿的比我還像新娘蛉迹。我一直安慰自己,他們只是感情好戈泼,可當(dāng)我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布婿禽。 她就那樣靜靜地躺著赏僧,像睡著了一般大猛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上淀零,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天挽绩,我揣著相機與錄音,去河邊找鬼驾中。 笑死唉堪,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的肩民。 我是一名探鬼主播唠亚,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼持痰!你這毒婦竟也來了灶搜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤工窍,失蹤者是張志新(化名)和其女友劉穎割卖,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體患雏,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡鹏溯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了淹仑。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丙挽。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖匀借,靈堂內(nèi)的尸體忽然破棺而出颜阐,到底是詐尸還是另有隱情,我是刑警寧澤怀吻,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布瞬浓,位于F島的核電站,受9級特大地震影響蓬坡,放射性物質(zhì)發(fā)生泄漏猿棉。R本人自食惡果不足惜磅叛,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望萨赁。 院中可真熱鬧弊琴,春花似錦、人聲如沸杖爽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽慰安。三九已至腋寨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間化焕,已是汗流浹背萄窜。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留撒桨,地道東北人查刻。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像凤类,于是被迫代替她去往敵國和親穗泵。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法谜疤,類相關(guān)的語法佃延,內(nèi)部類的語法,繼承相關(guān)的語法茎截,異常的語法苇侵,線程的語...
    子非魚_t_閱讀 31,639評論 18 399
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)企锌,斷路器榆浓,智...
    卡卡羅2017閱讀 134,661評論 18 139
  • 一. Java基礎(chǔ)部分.................................................
    wy_sure閱讀 3,811評論 0 11
  • 作者:Benjamin H. Sigelman, Luiz Andr′e Barroso, Mike Burrow...
    Josh_Song閱讀 1,233評論 0 8
  • 今天白天陡鹃,我在微博上發(fā)了好幾條關(guān)于“小彩旗在春晚的四小時旋轉(zhuǎn)是不是當(dāng)代藝術(shù)”的討論,貌似很少人搭理呀抖坪,而且少數(shù)搭理...
    雕爺閱讀 2,071評論 3 8