zoukankan      html  css  js  c++  java
  • 基于轻量级ORM框架Dapper的扩展说明

    这里简单的介绍一下本人基于Dapper作的一些简单的扩展,供大家参考。

    为何要使用这款框架,相信大家看到下面排名就清楚了

    其实在各大网站上,我们大概都会看到这样的一个对比效果图,在超过500次poco serialization的过程中所表现的性能,我们发现dapper是第二名,

    当然第一名谁也无法超越,越底层的当然久越快,同时也就越麻烦。

    至于如何使用进行基本的数据操作,我这里就不再阐述,http://www.cnblogs.com/Sinte-Beuve/p/4231053.html这里介绍了Dapper的基本使用的方法。

    一.文件说明,打包的文件如下

    SqlMapperExtensions类:ORM扩展类,基于SQLMapper类的扩展。
    SqlMapper类--Dapper原始类:一些底层封装代码,使用时可查看其实现原理。
    生成实体类_Dapper_模板文件:用于动态生成实体类的模板,配合DOS生成工具使用。

    二.扩展类新增的几个方法

    SqlMapperExtensions类中新增: UpdateGiven()、InsertGiven()、GetPageList()方法。

    UpdateGiven():更新时只更新赋值的字段

    InsertGiven():插入时只插入赋值的字段

    GetPageList():新增分页查询

    另新增数据库环境支持Oracle

    三.举栗子

    这里用上面的方法来简单的测试一下。

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Data;
     4 using System.Data.SqlClient;
     5 using System.Linq;
     6 using System.Text;
     7 using System.Threading.Tasks;
     8 using Dapper;
     9 using System.Data.OracleClient;
    10 using Dapper.Contrib.Extensions;
    11 using Dapper.Contrib;
    12 using Dapper.Model;
    13 namespace ConsoleTest1
    14 {
    15     class Program
    16     {
    18         static IDbConnection conn = new OracleConnection("Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=*.*.*.*)(PORT=1521)))(CONNECT_DATA=(service_name =*)));Persist Security Info=True;User ID=*; Password=*;");
    19         static void Main(string[] args)
    20         {
    21             //创建Book表
    22             conn.Execute(@" create table Book (Id number, Name nvarchar2(100) not null),Remark nvarchar2(200)");
    23             Console.WriteLine("Created database");
    24             BOOK book = new BOOK();
    25             book.NAME = "C#本质论";
    26             book.ID = 1001;
    27             string query = "INSERT INTO Book(Id,Name)VALUES(@Id,@Name)";
    28             //对对象进行操作
    29             conn.Execute(query, book);//原始操作 传入sql语句和参数
    30 
    31             ////以下是扩展中的方式
    32             //直接用Insert虽然只给了部分字段,但会插入所有字段,造成数据库的默认值会被覆盖的情况
    33             conn.Insert<BOOK>(new BOOK { ID = 1004, NAME = "Dapper" });
    34             conn.InsertGiven<BOOK>(new BOOK { ID = 1004, NAME = "Dapper" });
    35             //每次执行Update方法也是会更新所有字段,没赋值的字段会覆盖掉原始数据库的值
    36             conn.Update<BOOK>(new BOOK { ID = 1004, NAME = "Dapper" });
    37             conn.UpdateGiven<BOOK>(new BOOK { ID = 1004, NAME = "update Dos way" });
    38             ////以下是分页查询,有一个重载
    39             long longCount;
    40             var sortlist=new List<ISort>();
    41             sortlist.Add(new Sort{ PropertyName="id",Ascending=true});
    42             //该方法要传入一个长整型变量供传递出查询的总量
    43             var pagebook = conn.GetPageList<BOOK>(0, 10, out longCount, new BOOK { ID=1004}, sortlist);
    44             //该重载不需要传入长整型变量
    45             var pagebook2 = conn.GetPageList<BOOK>(0, 10, null, sortlist);
    46 
    47         }
    48     }
    49 
    50 }

    其中具体方式的实现分别如下:

     1         /// <summary>
     2         /// Inserts an entity into table "Ts" and returns identity id.(Insert the given fields)
     3         /// </summary>
     4         /// <param name="connection">Open SqlConnection</param>
     5         /// <param name="entityToInsert">Entity to insert</param>
     6         /// <returns>Identity of inserted entity</returns>
     7         public static long InsertGiven<T>(this IDbConnection connection, T entityToInsert, IDbTransaction transaction = null, int? commandTimeout = null) where T : Entity
     8         {
     9             var type = typeof(T);
    10             var name = GetTableName(type);
    11             var mfields = entityToInsert.GetModifyFields();
    12             if (null == mfields || mfields.Count == 0)
    13                 return -1;
    14             var sbColumnList = new StringBuilder(null);
    15             SetSqlConnectTag(connection);//根据不同数据库设置标记符 SqlServer@ Oracle:
    16             var keyProperties = KeyPropertiesCache(type);
    17             for (var i = 0; i < mfields.Count; i++)
    18             {
    19                 sbColumnList.AppendFormat("{0}", mfields[i].Field);
    20                 if (i < mfields.Count - 1)
    21                     sbColumnList.Append(", ");
    22             }
    23             var sbParameterList = new StringBuilder(null);
    24             for (var i = 0; i < mfields.Count; i++)
    25             {
    26                 sbParameterList.AppendFormat("{0}{1}", SqlConnectTag, mfields[i].Field);
    27                 if (i < mfields.Count - 1)
    28                     sbParameterList.Append(", ");
    29             }
    30             var adapter = GetFormatter(connection);
    31             return adapter.Insert(connection, transaction, commandTimeout, name, sbColumnList.ToString(),
    32                 sbParameterList.ToString(), keyProperties, entityToInsert);
    33         }
    InsertGiven
     1         /// <summary>
     2         /// Updates entity in table "Ts", checks if the entity is modified if the entity is tracked by the Get() extension.
     3         /// update the given fileds
     4         /// </summary>
     5         /// <typeparam name="T">Type to be updated</typeparam>
     6         /// <param name="connection">Open SqlConnection</param>
     7         /// <param name="entityToUpdate">Entity to be updated</param>
     8         /// <returns>true if updated, false if not found or not modified (tracked entities)</returns>
     9         public static bool UpdateGiven<T>(this IDbConnection connection, T entityToUpdate, IDbTransaction transaction = null, int? commandTimeout = null) where T : Entity
    10         {
    11             var proxy = entityToUpdate as IProxy;
    12             if (proxy != null)
    13             {
    14                 if (!proxy.IsDirty) return false;
    15             }
    16 
    17             var type = typeof(T);
    18 
    19             var keyProperties = KeyPropertiesCache(type);
    20             if (!keyProperties.Any())
    21                 throw new ArgumentException("Entity must have at least one [Key] property");
    22 
    23             var name = GetTableName(type);
    24 
    25             var mfields = entityToUpdate.GetModifyFields();
    26             if (null == mfields || mfields.Count == 0)
    27                 return false;
    28             for (var i = 0; i < keyProperties.Count(); i++)
    29             {//排除主键
    30                 var property = keyProperties.ElementAt(i);
    31                 if (mfields.Select(t => t.Field).Contains(property.Name))
    32                     mfields.Remove(mfields.FirstOrDefault(t=>t.Field==property.Name));
    33             }
    34             var sb = new StringBuilder();
    35             sb.AppendFormat("update {0} set ", name);
    36             SetSqlConnectTag(connection);//根据不同数据库设置标记符 SqlServer@ Oracle:
    37             for (var i = 0; i < mfields.Count; i++)
    38             {
    39                 sb.AppendFormat("{0} = {2}{1}", mfields[i].Field, mfields[i].Field, SqlConnectTag);
    40                 if (i < mfields.Count - 1)
    41                     sb.AppendFormat(", ");
    42             }
    43             sb.Append(" where ");
    44             for (var i = 0; i < keyProperties.Count(); i++)
    45             {
    46                 var property = keyProperties.ElementAt(i);
    47                 sb.AppendFormat("{0} = {2}{1}", property.Name, property.Name, SqlConnectTag);
    48                 if (i < keyProperties.Count() - 1)
    49                     sb.AppendFormat(" and ");
    50             }
    51             var updated = connection.Execute(sb.ToString(), entityToUpdate, commandTimeout: commandTimeout, transaction: transaction);
    52             return updated > 0;
    53         }
    UpdateGiven
     1  /// <summary>
     2         /// Paging
     3         /// </summary>
     4         /// <typeparam name="T">传入实体类型</typeparam>
     5         /// <param name="connection">此连接</param>
     6         /// <param name="pageIndex">第几页:0为第一页开始</param>
     7         /// <param name="pageSize">每页数量</param>
     8         /// <param name="allRowsCount">返回满足条件总量</param>
     9         /// <param name="entityToPredicate">条件:实体传入</param>
    10         /// <param name="sort">排序条件:ISort列表方式传入</param>
    11         /// <param name="buffered">是否缓存</param>
    12         /// <returns></returns>
    13         public static IEnumerable<T> GetPageList<T>(this IDbConnection connection, int pageIndex, int pageSize, out long allRowsCount,
    14         T entityToPredicate = null, IList<ISort> sort = null, bool buffered = true) where T : Entity
    15         {
    16             DynamicParameters dynamicParameters = new DynamicParameters();
    17             var type = typeof(T);
    18             SetSqlConnectTag(connection);//根据不同数据库设置标记符 SqlServer@ Oracle:
    19             var keys = KeyPropertiesCache(type);
    20             if (keys.Count() > 1)
    21                 throw new DataException("Get<T> only supports an entity with a single [Key] property");
    22             if (!keys.Any())
    23                 throw new DataException("Get<T> only supports en entity with a [Key] property");
    24 
    25             var onlyKey = keys.First();
    26             StringBuilder innersql = new StringBuilder(string.Format("SELECT * FROM {0}",
    27                 GetTableName(type)));
    28             if (entityToPredicate != null)
    29             {
    30                 var mfields = entityToPredicate.GetModifyFields();
    31                 innersql.Append(" where ");
    32                 for (var i = 0; i < mfields.Count; i++)
    33                 {
    34                     innersql.AppendFormat("{0} = {2}{1}", mfields[i].Field, mfields[i].Field, SqlConnectTag);
    35                     if (i < mfields.Count - 1)
    36                         innersql.AppendFormat(", ");
    37                     dynamicParameters.Add(mfields[i].Field, mfields[i].NewValue);
    38                 }
    39             }
    40             if (sort != null && sort.Any())
    41             {
    42                 innersql.Append(" ORDER BY ")
    43                     .Append(sort.Select(s => s.PropertyName + (s.Ascending ? " ASC" : " DESC")).AppendStrings());
    44             }
    45             allRowsCount = connection.Query(innersql.ToString(), entityToPredicate).Count();
    46             Dictionary<string, object> parameters = new Dictionary<string, object>();
    47             string sql = GetFormatter(connection).GetPagingSql(innersql.ToString(), pageIndex, pageSize, parameters);
    48             foreach (var parameter in parameters)
    49             {
    50                 dynamicParameters.Add(parameter.Key, parameter.Value);
    51             }
    52             return connection.Query<T>(sql, dynamicParameters);
    53         }

    下面我们来调试一下来看看Insert和InsertGiven、Update和UpdateGiven的区别吧

    1  ////以下是扩展中的方式
    2   //直接用Insert虽然只给了部分字段,但会插入所有字段,造成数据库的默认值会被覆盖的情况
    3   conn.Insert<BOOK>(new BOOK { ID = 1004, NAME = "Dapper" });
    4   conn.InsertGiven<BOOK>(new BOOK { ID = 1004, NAME = "Dapper" });
    5   //每次执行Update方法也是会更新所有字段,没赋值的字段会覆盖掉原始数据库的值
    6   conn.Update<BOOK>(new BOOK { ID = 1004, NAME = "Dapper" });
    7   conn.UpdateGiven<BOOK>(new BOOK { ID = 1004, NAME = "update Dos way" });

    Insert生成的sql语句:

    InsertGiven生成的sql语句:

    Update生成的sql语句:

    UpdateGiven生成的sql语句:

    想必扩展的方法个中缘由就一清二楚了。

    四.实体类生成

    其中BOOK实体类如何生成?这里借鉴了DOS生成实体类工具,并新增了一个模板文件->生成实体类_Dapper_模板文件.tpl

    打开DOSTOOL的Debug文件,将其放入模板文件中,重新打开DOSTOOL文件便可看见新增了一个模板,选择其模板,生成代码即可。

     

    以上。

  • 相关阅读:
    BFS模板 + 力扣例题
    和小吴日常3
    和小吴日常2
    Cocos Creator 学习记录
    js浏览器事件循环机制
    vue+uniapp 项目中一些常用知识
    JSP第一次作业
    Test
    InnoDB存储引擎
    MySQL存储引擎
  • 原文地址:https://www.cnblogs.com/hxzblog/p/7462229.html
Copyright © 2011-2022 走看看