zoukankan      html  css  js  c++  java
  • 对Dapper的一点改造

              微软推出的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.

      

    using System;
    using System.Collections.Generic;
    using System.Linq.Expressions;
    using System.Reflection;
    using System.Text;
    
    namespace Microsofot.Core
    {
    /// <summary>
    /// Lambda帮助
    /// !item.IsDeleted ===> item.IsDeleted == false 
    /// menuIds.Contains(item.Id) + new { @Id = menuIds }
    /// 请不要传递IEnumerable<TSource>因为不认识
    /// </summary>
    public static class LambdaHelper
    {
    
    /// <summary>
    /// 查询
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="func"></param>
    /// <returns></returns>
    public static string Query<T>(Expression<Func<T, bool>> func) where T : class
    {
    string res = string.Empty;
    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 = string.Empty;
    }
    var a1 = func.GetType().FullName;
    var a2 = a1.Split('.')[6];
    var a3 = a2.Split(',')[0];
    res = "select * from " + a3 + " where" + res;
    return res;
    }
    
    /// <summary>
    /// 插入(支持单条和批量)
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="model"></param>
    /// <returns></returns>
    public static string Insert<T>(T model)
    {
    var sql = "insert into " + model.GetType().Name + " values (";
    var dic = GetProperties(model);
    
    for (int i = 0; i < dic.Count; i++)
    {
    if (i == 4)
    {
    //跳过主键
    continue;
    }
    
    if (dic.Count - 1 > i)
    {
    sql += "@" + dic[i] + ",";
    }
    
    if (dic.Count - 1 == i)
    {
    sql += "@" + dic[i] + ")";
    }
    }
    return sql;
    }
    
    /// <summary>
    /// 修改(支持单条和批量)
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="model"></param>
    /// <returns></returns>
    public static string Update<T>(T model)
    {
    var sql = "update " + model.GetType().Name + " set ";
    
    var dic = new Dictionary<object, object>();
    if (model == null) { return null; }
    PropertyInfo[] properties = model.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
    if (properties.Length <= 0) { return null; }
    int a = 0;
    foreach (PropertyInfo item in properties)
    {
    string name = item.Name;
    object value = item.GetValue(model, null);
    if (item.PropertyType.IsValueType || item.PropertyType.Name.StartsWith("String"))
    {
    dic.Add(a, name+","+ value);
    a++;
    }
    }
    
    
    for (int i = 0; i < dic.Count; i++)
    {
    var split = dic[i].ToString().Split(',');
    if (i == 4)
    {
    //跳过主键
    continue;
    }
    
    if (dic.Count - 1 > i)
    {
    //非最后一个字段拼接sql加逗号
    if (!string.IsNullOrWhiteSpace(split[1]))
    {
    sql += split[0] + "=@" + split[0] + ",";
    }
    
    }
    
    if (dic.Count - 1 == i)
    {
    var id = dic[4].ToString().Split(',');
    if (!string.IsNullOrWhiteSpace(split[1]))
    {
    sql += split[0] + "=@" + split[0];
    }
    
    sql += " where "+ id[0] + "=@" + id[0];
    }
    }
    return sql;
    }
    
    /// <summary>
    /// 逻辑删除(支持单条和批量)
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="model"></param>
    /// <returns></returns>
    public static string Delete<T>(T model)
    {
    var sql = "update " + model.GetType().Name + " set ";
    
    var dic = new Dictionary<object, object>();
    if (model == null) { return null; }
    PropertyInfo[] properties = model.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
    if (properties.Length <= 0) { return null; }
    int a = 0;
    foreach (PropertyInfo item in properties)
    {
    string name = item.Name;
    object value = item.GetValue(model, null);
    if (item.PropertyType.IsValueType || item.PropertyType.Name.StartsWith("String"))
    {
    dic.Add(a, name + "," + value);
    a++;
    }
    }
    var id = dic[4].ToString().Split(',');
    
    sql += " IsDeleted='true'";
    sql += " where " + id[0] + "=@" + id[0];
    
    return sql;
    }
    
    /// <summary>
    /// 排序
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="exp"></param>
    /// <param name="desc">true顺序false倒序</param>
    /// <returns></returns>
    public static string Order<T>(Expression<Func<T, object>> exp,bool desc) where T : class
    {
    string orderby = " order by";
    var res = string.Empty;
    if (exp.Body is UnaryExpression)
    {
    UnaryExpression ue = ((UnaryExpression)exp.Body);
    res = ExpressionRouter(ue.Operand).ToLower() ;
    }
    else
    {
    MemberExpression order = ((MemberExpression)exp.Body);
    res = order.Member.Name.ToLower() ;
    }
    if (desc)
    {
    res = $"{orderby} '{res}'";
    }
    else
    {
    res = $"{orderby} '{res}' desc";
    }
    
    return res;
    }
    
    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[exps.Length-1].Split(new char[] { ')' })[0];
    
    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 + " in @" + 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;
    }
    }
    
    /// <summary>
    /// 读取实体的属性字段和值
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="t"></param>
    /// <returns></returns>
    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;
    }
    
    }
    }

    以上是将Lambda转换为Sql的帮助类

    using Microsofot.Core;
    using Microsoft.Data;
    using Microsoft.Entity;
    using Microsoft.Service.Interface;
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Linq.Expressions;
    
    namespace Microsoft.Service.Service
    {
        /// <summary>
        /// 访问服务
        /// </summary>
        public class PageViewService: IPageViewService
        {
            /// <summary>
            /// 查询
            /// </summary>
            /// <param name="exp"></param>
            /// <returns></returns>
            public List<PageView> Query(Expression<Func<PageView, bool>> exp, Expression<Func<PageView, object>> order, bool desc, object param = null)
            {
                List<PageView> result = null;
                if (exp != null)
                {
                    var sql = LambdaHelper.Query(exp) + LambdaHelper.Order(order, desc);
                    if (!string.IsNullOrWhiteSpace(sql))
                    {
                        result = DapperManager.Query<PageView>(sql,param).ToList();
                        LogHelper.Info("PageViewService.Query:" + result.Count);
                    }
                }
                return result;
            }
    
            /// <summary>
            /// 单条插入
            /// </summary>
            /// <param name="model"></param>
            /// <returns></returns>
            public int Insert(PageView model)
            {
                int result = -1;
                if (model != null)
                {
                    string sql = LambdaHelper.Insert(model);
                    result = DapperManager.Execute(sql, model, null, null, CommandType.Text);
                    LogHelper.Info("PageViewService.Insert:" + result);
                }
                return result;
            }
    
            /// <summary>
            /// 批量插入
            /// </summary>
            /// <param name="model"></param>
            /// <returns></returns>
            public int Insert(List<PageView> model)
            {
                int result = -1;
                if (model != null)
                {
                    string sql = LambdaHelper.Insert(model.Last());
                    result = DapperManager.Execute(sql, model, null, null, CommandType.Text);
                    LogHelper.Info("PageViewService.Insert:" + result);
                }
                return result;
            }
    
            /// <summary>
            /// 单条修改
            /// </summary>
            /// <param name="model"></param>
            /// <returns></returns>
            public int Update(PageView model)
            {
                int result = -1;
                if (model != null)
                {
                    string sql = LambdaHelper.Update(model);
                    result = DapperManager.Execute(sql, model, null, null, CommandType.Text);
                    LogHelper.Info("PageViewService.Update:" + result);
                }
                return result;
            }
    
            /// <summary>
            /// 多条修改
            /// </summary>
            /// <param name="model"></param>
            /// <returns></returns>
            public int Update(List<PageView> model)
            {
                int result = -1;
                if (model != null)
                {
                    string sql = LambdaHelper.Update(model.Last());
                    result = DapperManager.Execute(sql, model, null, null, CommandType.Text);
                    LogHelper.Info("PageViewService.Update:" + result);
                }
                return result;
            }
    
            /// <summary>
            /// 单条删除
            /// </summary>
            /// <param name="id"></param>
            /// <returns></returns>
            public int Delete(PageView model)
            {
                int result = -1;
                if (model != null)
                {
                    string sql = LambdaHelper.Delete(model);
                    result = DapperManager.Execute(sql, model, null, null, CommandType.Text);
                    LogHelper.Info("PageViewService.Delete:" + result);
                }
                return result;
            }
    
            /// <summary>
            /// 多条删除
            /// </summary>
            /// <param name="id"></param>
            /// <returns></returns>
            public int Delete(List<PageView> model)
            {
                int result = -1;
                if (model != null)
                {
                    string sql = LambdaHelper.Delete(model.Last());
                    result = DapperManager.Execute(sql, model, null, null, CommandType.Text);
                    LogHelper.Info("PageViewService.Delete:" + result);
                }
                return result;
            }
    
            /// <summary>
            /// 原生Dapper查询
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="sql"></param>
            /// <param name="param"></param>
            /// <param name="transaction"></param>
            /// <param name="buffered"></param>
            /// <param name="commandTimeout"></param>
            /// <param name="commandType"></param>
            /// <returns></returns>
            public List<T> Query<T>(string sql, object param = null, IDbTransaction transaction = null, bool buffered = true, int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
            {
                return DapperManager.Query<T>(sql, param, transaction, buffered, commandTimeout, commandType).ToList();
            }
            /// <summary>
            /// 原生Dapper增、删、改、存储过程方法
            /// </summary>
            /// <param name="sql"></param>
            /// <param name="parms"></param>
            /// <returns></returns>
            public int Execute(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = default(int?), CommandType? commandType = default(CommandType?))
            {
                return DapperManager.Execute(sql, param, transaction, commandTimeout, commandType);
            }
        }
    }

       以上调用案例就和EF很像了.

               但是底层还是保持着Dapper的模式.

                       至于性能比之原生Dapper或者EF6.0.

                                  有空的各位就可以试试了

  • 相关阅读:
    20161020001 DataGridView 选中的 DataGridViewCheckBoxCell 不添加重复项
    20161014006 DataGridView Combobox 数据绑定与传值
    Unity学习链接
    射线碰撞【拖拽物体img,点击后在固定位置显示A(工具),点击A显示B(Toggle组成的表),关闭B显示C(工具)】
    UGUI Text文字左右循环运动
    3d物体平缓摆动
    【转】unity www读取本地视频文件和外部视频文件 播放视频动画和视频声音
    改变图片或文字颜色( Gradient)
    改变图片透明度
    Animation脚本
  • 原文地址:https://www.cnblogs.com/Gao1234/p/8041711.html
Copyright © 2011-2022 走看看