基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil

匿名 (未验证) 提交于 2019-12-02 22:06:11

基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil,把日常能用到的各种CRUD都进行了简化封装,让普通程序员只需关注业务即可,因为非常简单,故直接贴源代码,大家若需使用可以直接复制到项目中,该SqlDapperUtil已广泛用于公司项目中。

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Dapper; using System.Data; using System.Data.Common; using System.Reflection; using System.IO; using System.Collections.Concurrent; using System.Data.SqlClient;  namespace Zuowj.Common {     /// <summary>     /// 基于Dapper的数据操作类封装的工具类     /// Author:左文俊     /// Date:2017/12/11     /// </summary>     public class SqlDapperUtil     {         private static string dbConnectionStringConfigPath = null;         private readonly static ConcurrentDictionary<string, bool> dbConnNamesCacheDic = new ConcurrentDictionary<string, bool>();          private string dbConnectionName = null;         private string dbConnectionString = null;         private string dbProviderName = null;         private IDbConnection dbConnection = null;         private bool useDbTransaction = false;         private IDbTransaction dbTransaction = null;           #region 私有方法          private IDbConnection GetDbConnection()         {             bool needCreateNew = false;             if (dbConnection == null || string.IsNullOrWhiteSpace(dbConnection.ConnectionString))             {                 needCreateNew = true;             }             else if (!MemoryCacheUtil.Contains(dbConnectionName))             {                 needCreateNew = true;             }              if (needCreateNew)             {                 dbConnectionString = GetDbConnectionString(dbConnectionName, out dbProviderName);                 var dbProviderFactory = DbProviderFactories.GetFactory(dbProviderName);                 dbConnection = dbProviderFactory.CreateConnection();                 dbConnection.ConnectionString = dbConnectionString;             }              if (dbConnection.State == ConnectionState.Closed)             {                 dbConnection.Open();             }              return dbConnection;         }          private string GetDbConnectionString(string dbConnName, out string dbProviderName)         {             //如果指定的连接字符串配置文件路径,则创建缓存依赖,一旦配置文件更改就失效,再重新读取             string[] connInfos = MemoryCacheUtil.GetOrAddCacheItem(dbConnName, () =>             {                 var connStrSettings = ConfigUtil.GetConnectionStringForConfigPath(dbConnName, SqlDapperUtil.DbConnectionStringConfigPath);                 string dbProdName = connStrSettings.ProviderName;                 string dbConnStr = connStrSettings.ConnectionString;                 //LogUtil.Info(string.Format("SqlDapperUtil.GetDbConnectionString>读取连接字符串配置节点[{0}]:{1},ProviderName:{2}", dbConnName, dbConnStr, dbProdName), "SqlDapperUtil.GetDbConnectionString");                 return new[] { EncryptUtil.Decrypt(dbConnStr), dbProdName };             }, SqlDapperUtil.DbConnectionStringConfigPath);              dbProviderName = connInfos[1];             return connInfos[0];         }           private T UseDbConnection<T>(Func<IDbConnection, T> queryOrExecSqlFunc)         {             IDbConnection dbConn = null;              try             {                 Type modelType = typeof(T);                 var typeMap = Dapper.SqlMapper.GetTypeMap(modelType);                 if (typeMap == null || !(typeMap is ColumnAttributeTypeMapper<T>))                 {                     Dapper.SqlMapper.SetTypeMap(modelType, new ColumnAttributeTypeMapper<T>());                 }                  dbConn = GetDbConnection();                 if (useDbTransaction && dbTransaction == null)                 {                     dbTransaction = GetDbTransaction();                 }                  return queryOrExecSqlFunc(dbConn);             }             catch             {                 throw;             }             finally             {                 if (dbTransaction == null && dbConn != null)                 {                     CloseDbConnection(dbConn);                 }             }         }          private void CloseDbConnection(IDbConnection dbConn, bool disposed = false)         {             if (dbConn != null)             {                 if (disposed && dbTransaction != null)                 {                     dbTransaction.Rollback();                     dbTransaction.Dispose();                     dbTransaction = null;                 }                  if (dbConn.State != ConnectionState.Closed)                 {                     dbConn.Close();                 }                 dbConn.Dispose();                 dbConn = null;             }         }          /// <summary>         /// 获取一个事务对象(如果需要确保多条执行语句的一致性,必需使用事务)         /// </summary>         /// <param name="il"></param>         /// <returns></returns>         private IDbTransaction GetDbTransaction(IsolationLevel il = IsolationLevel.Unspecified)         {             return GetDbConnection().BeginTransaction(il);         }          private DynamicParameters ToDynamicParameters(Dictionary<string, object> paramDic)         {             return new DynamicParameters(paramDic);         }          #endregion          public static string DbConnectionStringConfigPath         {             get             {                 if (string.IsNullOrEmpty(dbConnectionStringConfigPath))//如果没有指定配置文件,则取默认的配置文件路径作为缓存依赖路径                 {                     dbConnectionStringConfigPath = BaseUtil.GetConfigPath();                 }                  return dbConnectionStringConfigPath;             }             set             {                 if (!string.IsNullOrWhiteSpace(value) && !File.Exists(value))                 {                     throw new FileNotFoundException("指定的DB连接字符串配置文件不存在:" + value);                 }                  //如果配置文件改变,则可能导致连接字符串改变,故必需清除所有连接字符串的缓存以便后续重新加载字符串                 if (!string.Equals(dbConnectionStringConfigPath, value, StringComparison.OrdinalIgnoreCase))                 {                     foreach (var item in dbConnNamesCacheDic)                     {                         MemoryCacheUtil.RemoveCacheItem(item.Key);                     }                 }                  dbConnectionStringConfigPath = value;             }         }          public SqlDapperUtil(string connName)         {             dbConnectionName = connName;             if (!dbConnNamesCacheDic.ContainsKey(connName)) //如果静态缓存中没有,则加入到静态缓存中             {                 dbConnNamesCacheDic[connName] = true;             }          }           /// <summary>         /// 使用事务         /// </summary>         public void UseDbTransaction()         {             useDbTransaction = true;         }           /// <summary>         /// 获取一个值,param可以是SQL参数也可以是匿名对象         /// </summary>         /// <typeparam name="T"></typeparam>         /// <param name="sql"></param>         /// <param name="param"></param>         /// <param name="transaction"></param>         /// <param name="commandTimeout"></param>         /// <param name="commandType"></param>         /// <returns></returns>         public T GetValue<T>(string sql, object param = null, int? commandTimeout = null, CommandType? commandType = null)         {             return UseDbConnection((dbConn) =>              {                  return dbConn.ExecuteScalar<T>(sql, param, dbTransaction, commandTimeout, commandType);              });         }          /// <summary>         /// 获取第一行的所有值,param可以是SQL参数也可以是匿名对象         /// </summary>         /// <param name="sql"></param>         /// <param name="param"></param>         /// <param name="transaction"></param>         /// <param name="commandTimeout"></param>         /// <param name="commandType"></param>         /// <returns></returns>         public Dictionary<string, dynamic> GetFirstValues(string sql, object param = null, int? commandTimeout = null, CommandType? commandType = null)         {             return UseDbConnection((dbConn) =>             {                 Dictionary<string, dynamic> firstValues = new Dictionary<string, dynamic>();                 List<string> indexColNameMappings = new List<string>();                 int rowIndex = 0;                 using (var reader = dbConn.ExecuteReader(sql, param, dbTransaction, commandTimeout, commandType))                 {                     while (reader.Read())                     {                         if ((++rowIndex) > 1) break;                         if (indexColNameMappings.Count == 0)                         {                             for (int i = 0; i < reader.FieldCount; i++)                             {                                 indexColNameMappings.Add(reader.GetName(i));                             }                         }                          for (int i = 0; i < reader.FieldCount; i++)                         {                             firstValues[indexColNameMappings[i]] = reader.GetValue(i);                         }                     }                     reader.Close();                 }                  return firstValues;              });         }          /// <summary>         /// 获取一个数据模型实体类,param可以是SQL参数也可以是匿名对象         /// </summary>         /// <typeparam name="T"></typeparam>         /// <param name="sql"></param>         /// <param name="param"></param>         /// <param name="transaction"></param>         /// <param name="commandTimeout"></param>         /// <param name="commandType"></param>         /// <returns></returns>         public T GetModel<T>(string sql, object param = null, int? commandTimeout = null, CommandType? commandType = null) where T : class         {             return UseDbConnection((dbConn) =>             {                 return dbConn.QueryFirstOrDefault<T>(sql, param, dbTransaction, commandTimeout, commandType);             });         }          /// <summary>         /// 获取符合条件的所有数据模型实体类列表,param可以是SQL参数也可以是匿名对象         /// </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> GetModelList<T>(string sql, object param = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null) where T : class         {             return UseDbConnection((dbConn) =>             {                 return dbConn.Query<T>(sql, param, dbTransaction, buffered, commandTimeout, commandType).ToList();             });         }          /// <summary>         /// 获取符合条件的所有数据并根据动态构建Model类委托来创建合适的返回结果(适用于临时性结果且无对应的模型实体类的情况)         /// </summary>         /// <typeparam name="T"></typeparam>         /// <param name="buildModelFunc"></param>         /// <param name="sql"></param>         /// <param name="param"></param>         /// <param name="buffered"></param>         /// <param name="commandTimeout"></param>         /// <param name="commandType"></param>         /// <returns></returns>         public T GetDynamicModel<T>(Func<IEnumerable<dynamic>, T> buildModelFunc, string sql, object param = null, bool buffered = true, int? commandTimeout = null, CommandType? commandType = null)         {             var dynamicResult = UseDbConnection((dbConn) =>            {                return dbConn.Query(sql, param, dbTransaction, buffered, commandTimeout, commandType);            });              return buildModelFunc(dynamicResult);         }          /// <summary>         /// 获取符合条件的所有指定返回结果对象的列表(复合对象【如:1对多,1对1】),param可以是SQL参数也可以是匿名对象         /// </summary>         /// <typeparam name="T"></typeparam>         /// <param name="sql"></param>         /// <param name="types"></param>         /// <param name="map"></param>         /// <param name="param"></param>         /// <param name="transaction"></param>         /// <param name="buffered"></param>         /// <param name="splitOn"></param>         /// <param name="commandTimeout"></param>         /// <param name="commandType"></param>         /// <returns></returns>          public List<T> GetMultModelList<T>(string sql, Type[] types, Func<object[], T> map, object param = null, bool buffered = true, string splitOn = "Id", int? commandTimeout = null, CommandType? commandType = null)         {             return UseDbConnection((dbConn) =>             {                 return dbConn.Query<T>(sql, types, map, param, dbTransaction, buffered, splitOn, commandTimeout, commandType).ToList();             });         }             /// <summary>         /// 执行SQL命令(CRUD),param可以是SQL参数也可以是要添加的实体类         /// </summary>         /// <param name="sql"></param>         /// <param name="param"></param>         /// <param name="transaction"></param>         /// <param name="commandTimeout"></param>         /// <param name="commandType"></param>         /// <returns></returns>         public bool ExecuteCommand(string sql, object param = null, int? commandTimeout = null, CommandType? commandType = null)         {             return UseDbConnection((dbConn) =>             {                 int result = dbConn.Execute(sql, param, dbTransaction, commandTimeout, commandType);                 return (result > 0);             });         }          /// <summary>         /// 批量转移数据(利用SqlBulkCopy实现快速大批量插入到指定的目的表及SqlDataAdapter的批量删除)         /// </summary>         public bool BatchMoveData(string srcSelectSql, string srcTableName, List<SqlParameter> srcPrimarykeyParams, string destConnName, string destTableName)         {              using (SqlDataAdapter srcSqlDataAdapter = new SqlDataAdapter(srcSelectSql, GetDbConnectionString(dbConnectionName, out dbProviderName)))             {                 DataTable srcTable = new DataTable();                 SqlCommand deleteCommand = null;                 try                 {                     srcSqlDataAdapter.AcceptChangesDuringFill = true;                     srcSqlDataAdapter.AcceptChangesDuringUpdate = false;                     srcSqlDataAdapter.Fill(srcTable);                      if (srcTable == null || srcTable.Rows.Count <= 0) return true;                      string notExistsDestSqlWhere = null;                     string deleteSrcSqlWhere = null;                      for (int i = 0; i < srcPrimarykeyParams.Count; i++)                     {                         string keyColName = srcPrimarykeyParams[i].ParameterName.Replace("@", "");                         notExistsDestSqlWhere += string.Format(" AND told.{0}=tnew.{0}", keyColName);                         deleteSrcSqlWhere += string.Format(" AND {0}=@{0}", keyColName);                     }                      string dbProviderName2 = null;                     using (var destConn = new SqlConnection(GetDbConnectionString(destConnName, out dbProviderName2)))                     {                         destConn.Open();                          string tempDestTableName = "#temp_" + destTableName;                         destConn.Execute(string.Format("select top 0 * into {0} from {1}", tempDestTableName, destTableName));                         string destInsertCols = null;                         using (var destSqlBulkCopy = new SqlBulkCopy(destConn))                         {                             try                             {                                 destSqlBulkCopy.BulkCopyTimeout = 120;                                 destSqlBulkCopy.DestinationTableName = tempDestTableName;                                 foreach (DataColumn col in srcTable.Columns)                                 {                                     destSqlBulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName);                                     destInsertCols += "," + col.ColumnName;                                 }                                  destSqlBulkCopy.BatchSize = 1000;                                 destSqlBulkCopy.WriteToServer(srcTable);                             }                             catch (Exception ex)                             {                                 //LogUtil.Error("SqlDapperUtil.BatchMoveData.SqlBulkCopy:" + ex.ToString(), "SqlDapperUtil.BatchMoveData");                             }                              destInsertCols = destInsertCols.Substring(1);                              destConn.Execute(string.Format("insert into {1}({0}) select {0} from {2} tnew where not exists(select 1 from {1} told where {3})",                                              destInsertCols, destTableName, tempDestTableName, notExistsDestSqlWhere.Trim().Substring(3)), null, null, 100);                         }                         destConn.Close();                     }                      deleteCommand = new SqlCommand(string.Format("DELETE FROM {0} WHERE {1}", srcTableName, deleteSrcSqlWhere.Trim().Substring(3)), srcSqlDataAdapter.SelectCommand.Connection);                     deleteCommand.Parameters.AddRange(srcPrimarykeyParams.ToArray());                     deleteCommand.UpdatedRowSource = UpdateRowSource.None;                     deleteCommand.CommandTimeout = 200;                      srcSqlDataAdapter.DeleteCommand = deleteCommand;                     foreach (DataRow row in srcTable.Rows)                     {                         row.Delete();                     }                      srcSqlDataAdapter.UpdateBatchSize = 1000;                     srcSqlDataAdapter.Update(srcTable);                     srcTable.AcceptChanges();                      return true;                 }                 catch (Exception ex)                 {                     //LogUtil.Error("SqlDapperUtil.BatchMoveData:" + ex.ToString(), "SqlDapperUtil.BatchMoveData");                     return false;                 }                 finally                 {                     if (deleteCommand != null)                     {                         deleteCommand.Parameters.Clear();                     }                 }             }          }          /// <summary>         /// 批量复制数据(把源DB中根据SQL语句查出的结果批量COPY插入到目的DB的目的表中)         /// </summary>         public TResult BatchCopyData<TResult>(string srcSelectSql, string destConnName, string destTableName, IDictionary<string, string> colMappings, Func<IDbConnection, TResult> afterCoppyFunc)         {              using (SqlDataAdapter srcSqlDataAdapter = new SqlDataAdapter(srcSelectSql, GetDbConnectionString(dbConnectionName, out dbProviderName)))             {                 DataTable srcTable = new DataTable();                 TResult copyResult = default(TResult);                 try                 {                     srcSqlDataAdapter.AcceptChangesDuringFill = true;                     srcSqlDataAdapter.AcceptChangesDuringUpdate = false;                     srcSqlDataAdapter.Fill(srcTable);                      if (srcTable == null || srcTable.Rows.Count <= 0) return copyResult;                       string dbProviderName2 = null;                     using (var destConn = new SqlConnection(GetDbConnectionString(destConnName, out dbProviderName2)))                     {                         destConn.Open();                         string tempDestTableName = "#temp_" + destTableName;                         destConn.Execute(string.Format("select top 0 * into {0} from {1}", tempDestTableName, destTableName));                         bool bcpResult = false;                         using (var destSqlBulkCopy = new SqlBulkCopy(destConn))                         {                             try                             {                                 destSqlBulkCopy.BulkCopyTimeout = 120;                                 destSqlBulkCopy.DestinationTableName = tempDestTableName;                                 foreach (var col in colMappings)                                 {                                     destSqlBulkCopy.ColumnMappings.Add(col.Key, col.Value);                                 }                                  destSqlBulkCopy.BatchSize = 1000;                                 destSqlBulkCopy.WriteToServer(srcTable);                                 bcpResult = true;                             }                             catch (Exception ex)                             {                                 //LogUtil.Error("SqlDapperUtil.BatchMoveData.SqlBulkCopy:" + ex.ToString(), "SqlDapperUtil.BatchMoveData");                             }                         }                          if (bcpResult)                         {                             copyResult = afterCoppyFunc(destConn);                         }                          destConn.Close();                     }                      return copyResult;                 }                 catch (Exception ex)                 {                     //LogUtil.Error("SqlDapperUtil.BatchCopyData:" + ex.ToString(), "SqlDapperUtil.BatchCopyData");                     return copyResult;                 }             }          }           /// <summary>         /// 当使用了事务,则最后需要调用该方法以提交所有操作         /// </summary>         /// <param name="dbTransaction"></param>         public void Commit()         {             try             {                 if (dbTransaction.Connection != null && dbTransaction.Connection.State != ConnectionState.Closed)                 {                     dbTransaction.Commit();                 }             }             catch             {                 throw;             }             finally             {                 if (dbTransaction.Connection != null)                 {                     CloseDbConnection(dbTransaction.Connection);                 }                 dbTransaction.Dispose();                 dbTransaction = null;                 useDbTransaction = false;                  if (dbConnection != null)                 {                     CloseDbConnection(dbConnection);                 }             }         }          /// <summary>         /// 当使用了事务,如果报错或需要中断执行,则需要调用该方法执行回滚操作         /// </summary>         /// <param name="dbTransaction"></param>         public void Rollback()         {             try             {                 if (dbTransaction.Connection != null && dbTransaction.Connection.State != ConnectionState.Closed)                 {                     dbTransaction.Rollback();                 }             }             catch             {                 throw;             }             finally             {                 if (dbTransaction.Connection != null)                 {                     CloseDbConnection(dbTransaction.Connection);                 }                  dbTransaction.Dispose();                 dbTransaction = null;                 useDbTransaction = false;             }         }          ~SqlDapperUtil()         {             try             {                 CloseDbConnection(dbConnection, true);             }             catch             { }         }      } } 

ColumnAttributeTypeMapper辅助类相关代码如下:(如果不考虑实体类的属性与表字段不一致的情况,如下映射类可以不需要添加,同时SqlDapperUtil中移除相关依赖ColumnAttributeTypeMapper逻辑即可)

using Dapper; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks;  namespace KYExpress.Common {     public class ColumnAttributeTypeMapper<T> : FallbackTypeMapper     {         public ColumnAttributeTypeMapper()             : base(new SqlMapper.ITypeMap[]                 {                     new CustomPropertyTypeMap(                        typeof(T),                        (type, columnName) =>                            type.GetProperties().FirstOrDefault(prop =>                                prop.GetCustomAttributes(false)                                    .OfType<ColumnAttribute>()                                    .Any(attr => attr.Name == columnName)                                )                        ),                     new DefaultTypeMap(typeof(T))                 })         {         }     }      [AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]     public class ColumnAttribute : Attribute     {         public string Name { get; set; }     }      public class FallbackTypeMapper : SqlMapper.ITypeMap     {         private readonly IEnumerable<SqlMapper.ITypeMap> _mappers;          public FallbackTypeMapper(IEnumerable<SqlMapper.ITypeMap> mappers)         {             _mappers = mappers;         }           public ConstructorInfo FindConstructor(string[] names, Type[] types)         {             foreach (var mapper in _mappers)             {                 try                 {                     ConstructorInfo result = mapper.FindConstructor(names, types);                     if (result != null)                     {                         return result;                     }                 }                 catch (NotImplementedException)                 {                 }             }             return null;         }          public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, string columnName)         {             foreach (var mapper in _mappers)             {                 try                 {                     var result = mapper.GetConstructorParameter(constructor, columnName);                     if (result != null)                     {                         return result;                     }                 }                 catch (NotImplementedException)                 {                 }             }             return null;         }          public SqlMapper.IMemberMap GetMember(string columnName)         {             foreach (var mapper in _mappers)             {                 try                 {                     var result = mapper.GetMember(columnName);                     if (result != null)                     {                         return result;                     }                 }                 catch (NotImplementedException)                 {                 }             }             return null;         }           public ConstructorInfo FindExplicitConstructor()         {             return _mappers                 .Select(mapper => mapper.FindExplicitConstructor())                 .FirstOrDefault(result => result != null);         }     }  } 

使用示例方法如下:

            //实例化SqlDapperUtil对象,构造函数是config文件中的connectionStrings的Name名             var dapper = new SqlDapperUtil("LmsConnectionString");              //查询1个值             DateTime nowTime = dapper.GetValue<DateTime>("select getdate() as nowtime");               //查询1行值,并转换成字典(这对于临时查询多个字段而无需定义实体类有用)             Dictionary<string, dynamic> rowValues = dapper.GetFirstValues("select 0 as col0,1 as col1,2 as col2");               //查询1行并返回实体类             Person person = dapper.GetModel<Person>("select '张三' as Name,22 as Age,'2018-1-1' as BirthDay,'中国广东深圳' as HomeAddr");               //查询1行表字段与实体类属性不一致映射             Person person2 = dapper.GetModel<Person>("select '张三' as Name,22 as Age,'2018-1-1' as BirthDay,'中国广东深圳' as HomeAddress");               //查询多行返回实体集合             var persons = dapper.GetModelList<Person>(@"select '张三' as Name,22 as Age,'2018-1-1' as BirthDay,'中国广东深圳' as HomeAddr union all                                                                             select '李四' as Name,25 as Age,'2018-10-1' as BirthDay,'中国广东深圳' as HomeAddress union all                                                                             select '王五' as Name,35 as Age,'1982-10-1' as BirthDay,'中国广东广州' as HomeAddress                                                                         ");               //查询多行返回1对1关联实体结果集             var personWithCarResult = dapper.GetMultModelList<Person>(@"select t1.*,t2.* from                                                                                                     (select '张三' as Name,22 as Age,'2018-1-1' as BirthDay,'中国广东深圳' as HomeAddr union all                                                                                                     select '李四' as Name,25 as Age,'2018-10-1' as BirthDay,'中国广东深圳' as HomeAddress union all                                                                                                     select '王五' as Name,35 as Age,'1982-10-1' as BirthDay,'中国广东广州' as HomeAddress)as t1 inner join                                                                                                     (                                                                                                     select '张三' as DriverName,'大众' as Brand,'2018-8-8' as ManufactureDate union all                                                                                                     select '李四' as DriverName,'奔驰' as Brand,'2018-1-8' as ManufactureDate union all                                                                                                     select '王五' as DriverName,'奥迪' as Brand,'2017-8-8' as ManufactureDate                                                                                                     )as t2                                                                                                     on t1.Name=t2.DriverName                                                                         ", new[] { typeof(Person), typeof(CarInfo) }, (objs) =>                                                                          {                                                                              Person personItem = objs[0] as Person;                                                                              CarInfo carItem = objs[1] as CarInfo;                                                                              personItem.Car = carItem;                                                                              return personItem;                                                                          }, splitOn: "DriverName");                 //查询多行返回1对多关联实体结果=personWithManyCars             List<Person> personWithManyCars = new List<Person>();             dapper.GetMultModelList<Person>(@"select t1.*,t2.* from                                                                                                     (select '张三' as Name,22 as Age,'2018-1-1' as BirthDay,'中国广东深圳' as HomeAddr union all                                                                                                     select '李四' as Name,25 as Age,'2018-10-1' as BirthDay,'中国广东深圳' as HomeAddress union all                                                                                                     select '王五' as Name,35 as Age,'1982-10-1' as BirthDay,'中国广东广州' as HomeAddress)as t1 inner join                                                                                                     (                                                                                                     select '张三' as DriverName,'大众' as Brand,'2018-8-8' as ManufactureDate union all                                                                                                     select '张三' as DriverName,'奔驰' as Brand,'2018-1-8' as ManufactureDate union all                                                                                                     select '张三' as DriverName,'奥迪' as Brand,'2017-8-8' as ManufactureDate                                                                                                     )as t2                                                                                                     on t1.Name=t2.DriverName                                                                         ", new[] { typeof(Person), typeof(CarInfo) }, (objs) =>                                                                         {                                                                             Person personItem = objs[0] as Person;                                                                             CarInfo carItem = objs[1] as CarInfo;                                                                              Person personItemMain = personWithManyCars.FirstOrDefault(p => p.Name == personItem.Name);                                                                             if (personItemMain == null)                                                                             {                                                                                 personItem.Cars = new List<CarInfo>();                                                                                 personItemMain = personItem;                                                                                 personWithManyCars.Add(personItemMain);                                                                             }                                                                              personItemMain.Cars.Add(carItem);                                                                             return personItemMain;                                                                          }, splitOn: "DriverName"); 

2.下面是演示如何进行增、删、改以及动态查询的情况:

            //使用事务创建多张表,多条SQL语句写在一起             try             {                 dapper.UseDbTransaction();                 dapper.ExecuteCommand(@"create table T_Person(Name nvarchar(20) primary key,Age int,BirthDay datetime,HomeAddress nvarchar(200));                                                     create table T_CarInfo(DriverName nvarchar(20) primary key,Brand nvarchar(50),ManufactureDate datetime)");                 dapper.Commit();             }             catch (Exception ex)             {                 dapper.Rollback();                 //记日志             }              //使用事务批量插入多张表的多个记录,多条SQL分多次执行(参数支持批量集合对象传入,无需循环)             try             {                 dapper.UseDbTransaction();                 dapper.ExecuteCommand(@"insert into T_Person select N'张三' as Name,22 as Age,'2018-1-1' as BirthDay,N'中国广东深圳' as HomeAddress union all select N'李四' as Name,25 as Age,'2018-10-1' as BirthDay,N'中国广东深圳' as HomeAddress union all select N'王五' as Name,35 as Age,'1982-10-1' as BirthDay,N'中国广东广州' as HomeAddress");                   var carInfos = dapper.GetModelList<CarInfo>(@" select N'张三' as DriverName,N'大众' as Brand,'2018-8-8' as ManufactureDate union all select N'李四' as DriverName,N'奔驰' as Brand,'2018-1-8' as ManufactureDate union all select N'王五' as DriverName,N'奥迪' as Brand,'2017-8-8' as ManufactureDate");                  dapper.ExecuteCommand(@"insert into T_CarInfo(DriverName,Brand,ManufactureDate) Values(@DriverName,@Brand,@ManufactureDate)", carInfos);                  dapper.Commit();             }             catch (Exception ex)             {                 dapper.Rollback();                 //记日志             }              //执行删除,有参数,参数可以是实体类、匿名对象、字典(如有需要,可以是集合,以支持批量操作)             bool deleteResult = dapper.ExecuteCommand("delete from T_CarInfo where DriverName=@DriverName", new { DriverName = "李四" });              //构建动态执行SQL语句(以下是更新,查询类似)             StringBuilder updateSqlBuilder = new StringBuilder();             var updateParams = new Dictionary<string, object>();              if (1 == 1)             {                 updateSqlBuilder.Append(",Age=@Age");                 updateParams["Age"] = 20;             }              if (2 == 2)             {                 updateSqlBuilder.Append(",BirthDay=@BirthDay");                 updateParams["BirthDay"] = Convert.ToDateTime("2010-1-1");             }              if (3 == 3)             {                 updateSqlBuilder.Append(",HomeAddress=@HomeAddress");                 updateParams["HomeAddress"] = "中国北京天安门";             }              string updateSql = string.Concat("update T_Person set ", updateSqlBuilder.ToString().TrimStart(','), "  where  Name=@Name");             updateParams["Name"] = "张三";              bool updateResult = dapper.ExecuteCommand(updateSql, updateParams);              //查询返回动态自定义结果,之所以不直接返回Dynamic就好,是因为可读性差,故尽可能的在执行后就转成指定的类型             Tuple<string, int> hasCarInfo = dapper.GetDynamicModel<Tuple<string, int>>((rs) =>             {                 var result = rs.First();                 return Tuple.Create<string, int>(result.Name, result.CarCount);             }, @"select a.Name,count(b.DriverName) as CarCount from T_Person a left join T_CarInfo b on a.Name=b.DriverName where a.Name=@Name group by a.Name", new { Name = "张三" }); 

3.还有两个方法:BatchCopyData、BatchMoveData,这是特殊封装的,不是基于Dapper而是基于原生的Ado.net及BCP,目的是快速大量跨DB跨表COPY数据或转移数据,使用也不复杂,建议想了解的网友可以查看我以往的文章

以上示例方法用到了两个类,如下:

        class Person         {             public string Name { get; set; }               public int Age { get; set; }              public DateTime BirthDay { get; set; }              [Column(Name = "HomeAddress")]             public string HomeAddr { get; set; }              public CarInfo Car { get; set; }              public List<CarInfo> Cars { get; set; }         }          class CarInfo         {             public string Brand { get; set; }              public DateTime ManufactureDate { get; set; }              public string DriverName { get; set; }         } 

SqlDapperUtil类中依赖了之前我封装的类:如:MemoryCacheUtil(本地内存依赖缓存实用工具类)、ConfigUtil(配置文件管理工具类)、EncryptUtil(加密工具类),如果项目中不想引用这些类,可以移除或改成其它方法即可。

另外说明一下,为了防止和减少因DB连接未及时释放导致的连接池不足等原因,故默认执行所有的CRUD方法都是用完即释放,但有一种情况不会释放就是使用了事务,若使用事务,则必需配套使用:UseDbTransaction、Commit、或失败执行Rollback,否则可能导致未能及时释放对象,当然最终当SqlDapperUtil实例被回收后事务若没有提交或回滚,会强制执行回滚操作并释放事务及连接对象,防止可能的资源浪费情况。

本来早就想总结一下这篇文章,但一直由于工作太忙没有时间,今天利用加班研究.NET CORE的空隙时间完成,请大家支持,有好东西我一定会分享的,虽然不一定高大上,但一定实用且项目中有实战过的。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!