日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Dapper源码学习和源码修改

發(fā)布時間:2023/12/4 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Dapper源码学习和源码修改 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

之前ORM比較火熱,自己也搞了個WangSql,但是感覺比較low,大家都說Dapper性能好,所以現(xiàn)在學(xué)習(xí)學(xué)習(xí)Dapper,下面簡單從宏觀層面講講我學(xué)習(xí)的Dapper。

再了解一個東西前,先得學(xué)會使用,我也不再贅述怎么使用,接轉(zhuǎn)一個文章吧

http://www.cnblogs.com/yankliu-vip/p/4182892.html

好就當學(xué)習(xí)了吧,該去看看源碼了,到底怎么實現(xiàn)和好在哪呢。

先上一張圖,已經(jīng)把SqlMapper.cs按類拆分了,同時我自己在學(xué)習(xí)過程中也刪了加了改了一些類。

?

當然最重要的類還是SqlMapper.cs這個類,那就開始吧。

本來想把這個SqlMapper.cs類代碼全部粘貼的發(fā)現(xiàn)太長了,就算了吧,就把一些關(guān)鍵代碼粘貼過來。

private static CacheInfo GetCacheInfo(Identity identity)

? ? ? ? {

? ? ? ? ? ? CacheInfo info;

? ? ? ? ? ? if (!TryGetQueryCache(identity, out info))

? ? ? ? ? ? {

? ? ? ? ? ? ? ? info = new CacheInfo();

? ? ? ? ? ? ? ? if (identity.parametersType != null)

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? if (typeof(string).IsAssignableFrom(identity.parametersType))

? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? info.ParamReader = delegate(IDbCommand cmd, object obj) { (new StringParameters() as IDynamicParameters).AddParameters(cmd, identity, obj); };

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? else if (typeof(IDictionary).IsAssignableFrom(identity.parametersType))

? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? info.ParamReader = delegate(IDbCommand cmd, object obj) { (new DictionaryParameters() as IDynamicParameters).AddParameters(cmd, identity, obj); };

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? ? ? else

? ? ? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? ? ? info.ParamReader = CreateParamInfoGenerator(identity);

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? SetQueryCache(identity, info);

? ? ? ? ? ? }

? ? ? ? ? ? return info;

? ? ? ? }

來來來,劃重點了?info.ParamReader = CreateParamInfoGenerator(identity);?看到?jīng)],這貨是干嘛的啊,哪里用的呢?

就這里用的,其實就是那是一個委托,主要用來創(chuàng)建Command的DataParameter的,不信看下面

private static IDbCommand SetupCommand(IDbConnection cnn, IDbTransaction transaction, string sql, Action<IDbCommand, object> paramReader, object obj, int? commandTimeout, CommandType? commandType)

? ? ? ? {

? ? ? ? ? ? var cmd = cnn.CreateCommand();

? ? ? ? ? ? var bindByName = GetBindByName(cmd.GetType());

? ? ? ? ? ? if (bindByName != null) bindByName(cmd, true);

? ? ? ? ? ? cmd.Transaction = transaction;

? ? ? ? ? ? cmd.CommandText = FormatSql(sql);

? ? ? ? ? ? if (commandTimeout.HasValue)

? ? ? ? ? ? ? ? cmd.CommandTimeout = commandTimeout.Value;

? ? ? ? ? ? if (commandType.HasValue)

? ? ? ? ? ? ? ? cmd.CommandType = commandType.Value;

? ? ? ? ? ? if (paramReader != null)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? paramReader(cmd, obj);

? ? ? ? ? ? }

? ? ? ? ? ? return cmd;

? ? ? ? }

又劃重點了,?paramReader(cmd, obj);?這里就是執(zhí)行委托創(chuàng)建Command的DataParameter了。

如果有人問為什么要這個呢,那就是你上面連Dapper基本使用都沒看啊,滾回去看看先。

舉個例子:

sql = "insert into Teacher(Id,Name) values(@Id,@Name)";

? ? ? ? ? ? ? ? string tid = Guid.NewGuid().ToString();

? ? ? ? ? ? ? ? teacher = new Teacher()

? ? ? ? ? ? ? ? {

? ? ? ? ? ? ? ? ? ? Id = tid,

? ? ? ? ? ? ? ? ? ? Name = "wang"

? ? ? ? ? ? ? ? };

? ? ? ? ? ? ? ? intResult = SqlMapper.Execute(conn, sql, teacher);

這里?SqlMapper.Execute(conn, sql, teacher);?參數(shù)teacher就是上面?paramReader(cmd, obj);對應(yīng)的參數(shù)obj,這個委托呢就是將自定義實體teacher變成cmd的Parameters。

那么你又要問了,怎么變的?額,這么嘛就是難點了....

回到上面看看,委托的創(chuàng)建?info.ParamReader = CreateParamInfoGenerator(identity);?

關(guān)鍵點也是難點啊同學(xué)們CreateParamInfoGenerator這個方法是干嘛的啊,就是創(chuàng)建委托的啊,你個白癡。


好了,方法給你了,自己看吧,注釋寫的多詳細的啊。恩....

WTF,英文的啊,不要緊有翻譯的,反正自己看吧,我來給你講怕誤人子弟啊。

就我刪減后的Dapper 來說入?yún)⒔馕霾糠制鋵嵕偷酱私Y(jié)束,什么鬼,毫無亮點,要你講有何用。

別急,別急,下面講講我修改部分。

使用中,我發(fā)現(xiàn)參數(shù)的這么寫?insert into Student(Id,Name,Tid) values(@Id,@Name,@Tid)?那如果我換了數(shù)據(jù)庫比如MySql又得改@為?,換成Oracle又得把@改成:,這是我不能忍受的其一。

使用中,我發(fā)現(xiàn)?sql = "delete from Student where Id=#Id#"; intResult = SqlMapper.Execute(conn, sql, "jkajskajsk");?報錯,為毛啊,連字符串入?yún)魅肽愣疾徽J識,這是我不能忍受其二。

以上問題,可能是我版本問題,我用的是Dapper NET2.0版本。

不管為什么,先解決這個兩個痛點。

?

問題一:

原因分析,主要是不知道數(shù)據(jù)庫類型造成的。

解決辦法,那我就提前告訴你,數(shù)據(jù)庫相關(guān)信息,我們采用一種驅(qū)動方式來設(shè)置數(shù)據(jù)庫相關(guān)信息。

我新建了個類DbProvider.cs

internal class DbProvider{ public bool UseParameterPrefixInSql { get; set; }
public bool UseParameterPrefixInParameter { get; set; }
public string ParameterPrefix { get; set; }}

?

很簡單,后期你可以自己擴展,??ParameterPrefix ?這個就是數(shù)據(jù)庫參數(shù)前綴,比如@ ? :

//dbProvider

? ? ? ? ? ? dbProvider = new DbProvider()

? ? ? ? ? ? {

? ? ? ? ? ? ? ? UseParameterPrefixInSql = true,

? ? ? ? ? ? ? ? UseParameterPrefixInParameter = true,

? ? ? ? ? ? ? ? ParameterPrefix = "@"

? ? ? ? ? ? };

在SqlMapper創(chuàng)建一個 dbProvider?構(gòu)造函數(shù)里面 對其初始化,具體值最好寫在web.config里面,初始化的時候去讀配置文件。

有了這個之前的SQL我們可以改改了?insert into Student(Id,Name,Tid) values(#Id#,#Name#,#Tid#)當然原來的寫法也是支持的,只不過現(xiàn)在這種寫法,保證的SQL參數(shù)的統(tǒng)一性,以后切換數(shù)據(jù)庫也容易多了。?

可是這樣寫了,能正常運行嗎?答案是NO,所以還需要下面的方法。

//我寫的

? ? ? ? internal static string FormatNameForSql(string parameterName)

? ? ? ? {

? ? ? ? ? ? return dbProvider.UseParameterPrefixInSql ? (dbProvider.ParameterPrefix + parameterName) : parameterName;

? ? ? ? }

? ? ? ? internal static string FormatNameForParameter(string parameterName)

? ? ? ? {

? ? ? ? ? ? return dbProvider.UseParameterPrefixInParameter ? (dbProvider.ParameterPrefix + parameterName) : parameterName;

? ? ? ? }

? ? ? ? internal static string FormatSql(string sql)

? ? ? ? {

? ? ? ? ? ? Regex regex = new Regex("#([a-zA-Z0-9_]+?)#", RegexOptions.IgnoreCase | RegexOptions.Multiline);

? ? ? ? ? ? var ms = regex.Matches(sql);

? ? ? ? ? ? foreach (Match item in ms)

? ? ? ? ? ? {

? ? ? ? ? ? ? ? sql = sql.Replace(item.Value, FormatNameForSql(item.Groups[1].Value));

? ? ? ? ? ? }

? ? ? ? ? ? return sql;

? ? ? ? }

主要是這個方法?FormatSql?什么時候調(diào)呢,在這里

好了,問題一,反正是解決了,下面看看問題二了。

?

問題二:

原因分析,

來來來,劃重點了?info.ParamReader = CreateParamInfoGenerator(identity);?看到?jīng)],這貨是干嘛的啊,哪里用的呢?

就這里用的,其實就是那是一個委托,主要用來創(chuàng)建Command的DataParameter的

引用的上面的,那個委托啊CreateParamInfoGenerator不支持String、Dictionary這種入?yún)⒃斐傻摹?/p>

解決辦法,既然那個委托不支持,我就給不同的類型創(chuàng)建不同的委托就行了啥。

我為繼承string類型的創(chuàng)建了一個委托,委托是執(zhí)行StringParameters實例的AddParameters方法。

我為繼承IDictionary類型的創(chuàng)建了一個委托,委托是執(zhí)行DictionaryParameters實例的AddParameters方法。

通過不同的委托就能實現(xiàn)不同入?yún)崿F(xiàn)給Command的Parameters創(chuàng)建賦值了,哈哈哈哈哈....當然你要實現(xiàn)int double ...都一樣的方法,加個類繼承IDynamicParameters即可。

現(xiàn)在這樣子都可以正常使用了

sql = "delete from Student where Id=#Id#";

? ? ? ? ? ? ? ? intResult = SqlMapper.Execute(conn, sql, "jkajskajsk");



? ? ? ? ? ? ? ? sql = "delete from Student where Id=#Id# and Name=@Name and Name=@Name1";

? ? ? ? ? ? ? ? Hashtable dic = new Hashtable();

? ? ? ? ? ? ? ? dic.Add("Id", "123");

? ? ? ? ? ? ? ? dic.Add("Name", "s1234");

? ? ? ? ? ? ? ? dic.Add("Name1", "d12345");

? ? ? ? ? ? ? ? intResult = SqlMapper.Execute(conn, sql, dic);

總結(jié):

這篇文章只是對Dapper入?yún)⑦M行的分析,出參還沒看呢,先這樣吧,有空再說.

原文地址:http://www.cnblogs.com/deeround/p/6612213.html


.NET社區(qū)新聞,深度好文,微信中搜索dotNET跨平臺或掃描二維碼關(guān)注

總結(jié)

以上是生活随笔為你收集整理的Dapper源码学习和源码修改的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。