對Dapper的一點改造

来源:http://www.cnblogs.com/Gao1234/archive/2017/12/15/8041711.html
-Advertisement-
Play Games

微軟推出的ORM,EF在我開發的項目中給我的感覺一直都是慢.優點是高度封裝的底層.便於開發.Dapper在多篇性能比較的網站中.都是名列前三.缺點是手寫SQL,不便於開發.如果能結合EF的優點和Dapper的優點.那麼此次改造相比原生Dapper是脫胎換骨的. 上圖是Dapper最簡單的語法.相比A ...


微軟推出的ORM,EF在我開發的項目中給我的感覺一直都是慢.優點是高度封裝的底層.便於開發.Dapper在多篇性能比較的網站中.都是名列前三.缺點是手寫SQL,不便於開發.如果能結合EF的優點和Dapper的優點.那麼此次改造相比原生Dapper是脫胎換骨的.

上圖是Dapper最簡單的語法.相比ADO.NET.只增加了輸出結果的序列化(LIst<T>)和輸入結果的封裝(List<T>).

上圖是EF6.0最簡單的查詢.完全封裝了底層.只要寫寫語法簡單的lamade表達式就能完成大部分開發.

在此我將結合EF的一部分優點(lambda)和Dapper的一部分優點(性能).做一點升級

public class DBHelper
{
//private volatile static SqlConnection _instance = null;
//private static readonly object lockHelper = new object();
//private DBHelper() { }
public static SqlConnection CreateConnection()
{
//if (_instance == null)
//{
// lock (lockHelper)
// {
// if (_instance == null)
// {
string connStr = ConfigurationManager.AppSettings["SqlConnStr"];
SqlConnection conn = new SqlConnection(connStr);
//_instance = conn;
// }
// }
//}
//string connStr = ConfigurationManager.AppSettings["SqlConnStr"];
//SqlConnection conn = new SqlConnection(connStr);
return conn;
}
/// <summary>
/// 單個數據集查詢
/// </summary>
/// <param name="sql"></param>
/// <param name="parms"></param>
/// <returns></returns>
public static List<TEntity> Query<TEntity>(string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
{
using (IDbConnection conn = CreateConnection())
{
return conn.Query<TEntity>(sql, param, transaction, buffered, commandTimeout, commandType).Distinct().ToList();
}
}
/// <summary>
/// 執行增、刪、改方法
/// </summary>
/// <param name="sql"></param>
/// <param name="parms"></param>
/// <returns></returns>
public static int Execute(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
{
using (IDbConnection conn = CreateConnection())
{
return conn.Execute(sql, param, transaction, commandTimeout, commandType);
}
}
}

以上是底層加入了垃圾回收的Dapper.

public static class LambdaToSql
{
#region 基礎方法
#region 獲取條件語句方法

public static string Where<T>(Expression<Func<T, bool>> func) where T : class
{
string res = "";
if (func.Body is BinaryExpression)
{
BinaryExpression be = ((BinaryExpression)func.Body);
res = BinarExpressionProvider(be.Left, be.Right, be.NodeType);
}
else if (func.Body is MethodCallExpression)
{
MethodCallExpression be = ((MethodCallExpression)func.Body);
res = ExpressionRouter(func.Body);
}
else
{
res = " 1=1";
}
var a1 = func.GetType().FullName;
var a2 = a1.Split(new string[] { "[[" }, StringSplitOptions.RemoveEmptyEntries);
var a3 = a2[2].Split(',');
var a4 = a3[0].Split('.')[1];
res = "select * from " + a4 + " where" + res;
return res;
}

#endregion 獲取條件語句方法

#region 生成Dapper插入語法
public static string Insert<T>(T model)
{
var sql = "insert into "+ model.GetType().Name+ " values (";
var dic= GetProperties(model);
//var data = dic["mu"];

//List<string> test = new List<string>();
//test.AddRange(dic.Keys);

//for (int i = 0; i < list.Count; i++)
//{
// Console.WriteLine(test[i] + list[test[i]]);
//}

for (int i = 1; i < dic.Count; i++)
{
//跳過主鍵
if (dic.Count - 1 > i)
{
sql += "@" + dic[i] + ",";
}

if (dic.Count-1==i)
{
sql += "@" + dic[i] + ")";
}
}
return sql;
}
#endregion

#region 獲取排序語句 order by

private static string GetOrderSql<T>(Expression<Func<T, object>> exp) where T : class
{
var res = "";
if (exp.Body is UnaryExpression)
{
UnaryExpression ue = ((UnaryExpression)exp.Body);
res = "order by `" + ExpressionRouter(ue.Operand).ToLower() + "`";
}
else
{
MemberExpression order = ((MemberExpression)exp.Body);
res = "order by `" + order.Member.Name.ToLower() + "`";
}
return res;
}

#endregion 獲取排序語句 order by
#endregion 基礎方法

#region 底層

//internal static bool In<T>(this T obj, T[] array)
//{
// return true;
//}
//internal static bool NotIn<T>(this T obj, T[] array)
//{
// return true;
//}

private static string GetValueStringByType(object oj)
{
if (oj == null)
{
return "null";
}
else if (oj is ValueType)
{
return oj.ToString();
}
else if (oj is string || oj is DateTime || oj is char)
{
return string.Format("'{0}'", oj.ToString());
}
else
{
return string.Format("'{0}'", oj.ToString());
}
}

private static string BinarExpressionProvider(Expression left, Expression right, ExpressionType type)
{
string sb = "(";
//先處理左邊
string reLeftStr = ExpressionRouter(left);
sb += reLeftStr;

sb += ExpressionTypeCast(type);

//再處理右邊
string tmpStr = ExpressionRouter(right);
if (tmpStr == "null")
{
if (sb.EndsWith(" ="))
{
sb = sb.Substring(0, sb.Length - 2) + " is null";
}
else if (sb.EndsWith("<>"))
{
sb = sb.Substring(0, sb.Length - 2) + " is not null";
}
}
else
{
//添加參數
sb += tmpStr;
}

return sb += ")";
}

private static string ExpressionRouter(Expression exp)
{
string sb = string.Empty;

if (exp is BinaryExpression)
{
BinaryExpression be = ((BinaryExpression)exp);
return BinarExpressionProvider(be.Left, be.Right, be.NodeType);
}
else if (exp is MemberExpression)
{
MemberExpression me = ((MemberExpression)exp);
if (!exp.ToString().StartsWith("value"))
{
return me.Member.Name;
}
else
{
var result = Expression.Lambda(exp).Compile().DynamicInvoke();
if (result == null)
{
return "null";
}
else if (result is ValueType)
{
return Convert.ToBoolean(result) ? "1" : "0";
//return Convert.ToString(result);
}
else if (result is string || result is DateTime || result is char)
{
return string.Format("'{0}'", result.ToString());
}
else if (result is int[])
{
var rl = result as int[];
StringBuilder sbIntStr = new StringBuilder();
sbIntStr.Append("(");
foreach (var r in rl)
{
if (sbIntStr.Length == 1)
sbIntStr.Append(Convert.ToString(r));
else
sbIntStr.Append("," + Convert.ToString(r));
}
sbIntStr.Append(")");
return sbIntStr.ToString();
}
else if (result is string[])
{
var rl = result as string[];
StringBuilder sbIntStr = new StringBuilder();
sbIntStr.Append("(");
foreach (var r in rl)
{
if (sbIntStr.Length == 1)
sbIntStr.Append("'" + r + "'");
else
sbIntStr.Append(",'" + r + "'");
}
sbIntStr.Append(")");
return sbIntStr.ToString();
}
}
}
else if (exp is NewArrayExpression)
{
NewArrayExpression ae = ((NewArrayExpression)exp);
StringBuilder tmpstr = new StringBuilder();
foreach (Expression ex in ae.Expressions)
{
tmpstr.Append(ExpressionRouter(ex));
tmpstr.Append(",");
}
//添加參數

return tmpstr.ToString(0, tmpstr.Length - 1);
}
else if (exp is MethodCallExpression)
{
MethodCallExpression mce = (MethodCallExpression)exp;

string value = ExpressionRouter(mce.Arguments[0]).Replace("'", "");
string[] exps = mce.ToString().Split(new char[] { '.' });
string fieldName = exps[1];

if (mce.Method.Name == "In")
return string.Format("{0} In ({1})", ExpressionRouter(mce.Arguments[0]), ExpressionRouter(mce.Arguments[1]));
else if (mce.Method.Name == "NotIn")
return string.Format("{0} Not In ({1})", ExpressionRouter(mce.Arguments[0]), ExpressionRouter(mce.Arguments[1]));
else if (mce.Method.Name == "Contains")
return fieldName + " like '%" + value + "%'";
else if (mce.Method.Name == "StartsWith")
return fieldName + " like '" + value + "%'";
else if (mce.Method.Name == "EndsWith")
return fieldName + " like '%" + value + "'";
}
else if (exp is ConstantExpression)
{
ConstantExpression ce = ((ConstantExpression)exp);
if (ce.Value == null)
{
return "null";
}
else if (ce.Value is ValueType)
{
return Convert.ToBoolean(ce.Value) ? "1" : "0";
//return Convert.ToString(ce.Value);
}
else if (ce.Value is string || ce.Value is DateTime || ce.Value is char)
{
return string.Format("'{0}'", Convert.ToString(ce.Value));
}

//對數值進行參數附加
}
else if (exp is UnaryExpression)
{
UnaryExpression ue = ((UnaryExpression)exp);

return ExpressionRouter(ue.Operand);
}
return null;
}

private static string ExpressionTypeCast(ExpressionType type)
{
switch (type)
{
case ExpressionType.And:
case ExpressionType.AndAlso:
return " AND ";

case ExpressionType.Equal:
return " =";

case ExpressionType.GreaterThan:
return " >";

case ExpressionType.GreaterThanOrEqual:
return ">=";

case ExpressionType.LessThan:
return "<";

case ExpressionType.LessThanOrEqual:
return "<=";

case ExpressionType.NotEqual:
return "<>";

case ExpressionType.Or:
case ExpressionType.OrElse:
return " Or ";

case ExpressionType.Add:
case ExpressionType.AddChecked:
return "+";

case ExpressionType.Subtract:
case ExpressionType.SubtractChecked:
return "-";

case ExpressionType.Divide:
return "/";

case ExpressionType.Multiply:
case ExpressionType.MultiplyChecked:
return "*";

default:
return null;
}
}


private static Dictionary<object, object> GetProperties<T>(T t)
{
var ret = new Dictionary<object, object>();
if (t == null) { return null; }
PropertyInfo[] properties = t.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
if (properties.Length <= 0) { return null; }
int i = 0;
foreach (PropertyInfo item in properties)
{
string name = item.Name;
object value = item.GetValue(t, null);
if (item.PropertyType.IsValueType || item.PropertyType.Name.StartsWith("String"))
{
ret.Add(i, name);
i++;
}
}
return ret;
}
#endregion 底層
}

以上是將Lambda轉換為Sql的幫助類

//查詢
Expression<Func<mm, bool>> exp = item => item.mu != null;
var sql = LambdaToSql.Where(exp);
var list = DBHelper.Query<mm>(sql).ToList();

//單條插入
mm model = new mm();
model.mu = "2017";
model.mu1 = "2018";
model.mu2 = "2019";

var insertsql= LambdaToSql.Insert(model);
var l2 = DBHelper.Execute(insertsql, model, null, null, CommandType.Text);

以上調用案例就和EF很像了.但是底層還是保持著Dapper的模式.至於性能比之原生Dapper或者EF6.0.有空的各位就可以試試了

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • using System.IO;using UnityEngine;using UnityEditor; public class TestSaveSprite{ [MenuItem("LLWH/SpriteSplit")] public static void SpriteSlice() { Te ...
  • REmote DIctionary Server(Redis) 是一個由Salvatore Sanfilippo寫的key-value存儲系統。 Redis是一個開源的使用ANSI C語言編寫、遵守BSD協議、支持網路、可基於記憶體亦可持久化的日誌型、Key-Value資料庫,並提供多種語言的API。 ...
  • 使用一個小例子來演示:創建一個普通類別: class Ax { private int _ID; public int ID { get { return _ID; } set { _ID = value; } } private string _Name; public string Name { ...
  • TPL 數據流庫向具有高吞吐量和低滯後時間的占用大量 CPU 和 I/O 操作的應用程式的並行化和消息傳遞提供了基礎。 它還能顯式控制緩存數據的方式以及在系統中移動的方式。 為了更好地瞭解數據流編程模型,請考慮一個以非同步方式從磁碟載入圖像並創建複合圖像的應用程式。 傳統編程模型通常需要使用回調和同步 ...
  • 策略模式,即規則在變化之中,結果終歸為一。公司給員工計算工資,如有加班費,差旅費,每個月的生活補帖等等其它費用需要計算。這個費的規則是不盡相同。 不管策略的規則怎樣,終歸需要計算出一個結果 工資:可以定義一個介面: interface IStrategy { double Cost(double b ...
  • C#中解決Response.AddHeader("Content-Disposition", "attachment; filename=" + filename)下載文件時文件名亂碼的問題 ...
  • 1)擴展方法是什麼? 擴展方法可以在不修改原有類的代碼前提下,給類“增加”一個方法。擴展方法雖然屬於靜態方法,但調用的語法卻和對象調用類似。直接用一個例子來演示擴展方法。 1.準備實體類 public class Person { public Person(string name, int age ...
  • 演示產品源碼下載地址:http://www.jinhusns.com ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...