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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Dapper源码学习和源码修改

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

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

再了解一個東西前,先得學會使用,我也不再贅述怎么使用,接轉一個文章吧

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

好就當學習了吧,該去看看源碼了,到底怎么實現和好在哪呢。

先上一張圖,已經把SqlMapper.cs按類拆分了,同時我自己在學習過程中也刪了加了改了一些類。

?

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

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

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);?看到沒,這貨是干嘛的啊,哪里用的呢?

就這里用的,其實就是那是一個委托,主要用來創建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);?這里就是執行委托創建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);?參數teacher就是上面?paramReader(cmd, obj);對應的參數obj,這個委托呢就是將自定義實體teacher變成cmd的Parameters。

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

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

關鍵點也是難點啊同學們CreateParamInfoGenerator這個方法是干嘛的啊,就是創建委托的啊,你個白癡。


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

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

就我刪減后的Dapper 來說入參解析部分其實就到此結束,什么鬼,毫無亮點,要你講有何用。

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

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

使用中,我發現?sql = "delete from Student where Id=#Id#"; intResult = SqlMapper.Execute(conn, sql, "jkajskajsk");?報錯,為毛啊,連字符串入參傳入你都不認識,這是我不能忍受其二。

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

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

?

問題一:

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

解決辦法,那我就提前告訴你,數據庫相關信息,我們采用一種驅動方式來設置數據庫相關信息。

我新建了個類DbProvider.cs

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

?

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

//dbProvider

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

? ? ? ? ? ? {

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

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

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

? ? ? ? ? ? };

在SqlMapper創建一個 dbProvider?構造函數里面 對其初始化,具體值最好寫在web.config里面,初始化的時候去讀配置文件。

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

可是這樣寫了,能正常運行嗎?答案是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?什么時候調呢,在這里

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

?

問題二:

原因分析,

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

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

引用的上面的,那個委托啊CreateParamInfoGenerator不支持String、Dictionary這種入參造成的。

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

我為繼承string類型的創建了一個委托,委托是執行StringParameters實例的AddParameters方法。

我為繼承IDictionary類型的創建了一個委托,委托是執行DictionaryParameters實例的AddParameters方法。

通過不同的委托就能實現不同入參實現給Command的Parameters創建賦值了,哈哈哈哈哈....當然你要實現int double ...都一樣的方法,加個類繼承IDynamicParameters即可。

現在這樣子都可以正常使用了

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);

總結:

這篇文章只是對Dapper入參進行的分析,出參還沒看呢,先這樣吧,有空再說.

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


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

總結

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

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。