基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil
基于Dapper二次封裝了一個易用的ORM工具類:SqlDapperUtil,把日常能用到的各種CRUD都進行了簡化封裝,讓普通程序員只需關(guān)注業(yè)務(wù)即可,因為非常簡單,故直接貼源代碼,大家若需使用可以直接復(fù)制到項目中,該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的數(shù)據(jù)操作類封裝的工具類/// 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){//如果指定的連接字符串配置文件路徑,則創(chuàng)建緩存依賴,一旦配置文件更改就失效,再重新讀取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>讀取連接字符串配置節(jié)點[{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>/// 獲取一個事務(wù)對象(如果需要確保多條執(zhí)行語句的一致性,必需使用事務(wù))/// </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);}#endregionpublic 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);}//如果配置文件改變,則可能導(dǎo)致連接字符串改變,故必需清除所有連接字符串的緩存以便后續(xù)重新加載字符串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)) //如果靜態(tài)緩存中沒有,則加入到靜態(tài)緩存中{dbConnNamesCacheDic[connName] = true;}}/// <summary>/// 使用事務(wù)/// </summary>public void UseDbTransaction(){useDbTransaction = true;}/// <summary>/// 獲取一個值,param可以是SQL參數(shù)也可以是匿名對象/// </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參數(shù)也可以是匿名對象/// </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>/// 獲取一個數(shù)據(jù)模型實體類,param可以是SQL參數(shù)也可以是匿名對象/// </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>/// 獲取符合條件的所有數(shù)據(jù)模型實體類列表,param可以是SQL參數(shù)也可以是匿名對象/// </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>/// 獲取符合條件的所有數(shù)據(jù)并根據(jù)動態(tài)構(gòu)建Model類委托來創(chuàng)建合適的返回結(jié)果(適用于臨時性結(jié)果且無對應(yīng)的模型實體類的情況)/// </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>/// 獲取符合條件的所有指定返回結(jié)果對象的列表(復(fù)合對象【如:1對多,1對1】),param可以是SQL參數(shù)也可以是匿名對象/// </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>/// 執(zhí)行SQL命令(CRUD),param可以是SQL參數(shù)也可以是要添加的實體類/// </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>/// 批量轉(zhuǎn)移數(shù)據(jù)(利用SqlBulkCopy實現(xiàn)快速大批量插入到指定的目的表及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>/// 批量復(fù)制數(shù)據(jù)(把源DB中根據(jù)SQL語句查出的結(jié)果批量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>/// 當(dāng)使用了事務(wù),則最后需要調(diào)用該方法以提交所有操作/// </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>/// 當(dāng)使用了事務(wù),如果報錯或需要中斷執(zhí)行,則需要調(diào)用該方法執(zhí)行回滾操作/// </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輔助類相關(guān)代碼如下:(如果不考慮實體類的屬性與表字段不一致的情況,如下映射類可以不需要添加,同時SqlDapperUtil中移除相關(guān)依賴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);}}}使用示例方法如下:
?1.先來模擬各種查詢數(shù)據(jù)(由于是直接寫模擬SQL輸出,故沒有條件,也便于大家COPY后直接可以測試結(jié)果)
//實例化SqlDapperUtil對象,構(gòu)造函數(shù)是config文件中的connectionStrings的Name名var dapper = new SqlDapperUtil("LmsConnectionString");//查詢1個值DateTime nowTime = dapper.GetValue<DateTime>("select getdate() as nowtime");//查詢1行值,并轉(zhuǎn)換成字典(這對于臨時查詢多個字段而無需定義實體類有用)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 allselect '李四' as Name,25 as Age,'2018-10-1' as BirthDay,'中國廣東深圳' as HomeAddress union allselect '王五' as Name,35 as Age,'1982-10-1' as BirthDay,'中國廣東廣州' as HomeAddress");//查詢多行返回1對1關(guān)聯(lián)實體結(jié)果集var personWithCarResult = dapper.GetMultModelList<Person>(@"select t1.*,t2.* from(select '張三' as Name,22 as Age,'2018-1-1' as BirthDay,'中國廣東深圳' as HomeAddr union allselect '李四' as Name,25 as Age,'2018-10-1' as BirthDay,'中國廣東深圳' as HomeAddress union allselect '王五' 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 allselect '李四' as DriverName,'奔馳' as Brand,'2018-1-8' as ManufactureDate union allselect '王五' as DriverName,'奧迪' as Brand,'2017-8-8' as ManufactureDate)as t2on 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對多關(guān)聯(lián)實體結(jié)果=personWithManyCarsList<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 allselect '李四' as Name,25 as Age,'2018-10-1' as BirthDay,'中國廣東深圳' as HomeAddress union allselect '王五' 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 allselect '張三' as DriverName,'奔馳' as Brand,'2018-1-8' as ManufactureDate union allselect '張三' as DriverName,'奧迪' as Brand,'2017-8-8' as ManufactureDate)as t2on 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.下面是演示如何進行增、刪、改以及動態(tài)查詢的情況:
//使用事務(wù)創(chuàng)建多張表,多條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();//記日志}//使用事務(wù)批量插入多張表的多個記錄,多條SQL分多次執(zhí)行(參數(shù)支持批量集合對象傳入,無需循環(huán))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();//記日志}//執(zhí)行刪除,有參數(shù),參數(shù)可以是實體類、匿名對象、字典(如有需要,可以是集合,以支持批量操作)bool deleteResult = dapper.ExecuteCommand("delete from T_CarInfo where DriverName=@DriverName", new { DriverName = "李四" });//構(gòu)建動態(tài)執(zhí)行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);//查詢返回動態(tài)自定義結(jié)果,之所以不直接返回Dynamic就好,是因為可讀性差,故盡可能的在執(zhí)行后就轉(zhuǎn)成指定的類型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數(shù)據(jù)或轉(zhuǎn)移數(shù)據(jù),使用也不復(fù)雜,建議想了解的網(wǎng)友可以查看我以往的文章
以上示例方法用到了兩個類,如下:
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(本地內(nèi)存依賴緩存實用工具類)、ConfigUtil(配置文件管理工具類)、EncryptUtil(加密工具類),如果項目中不想引用這些類,可以移除或改成其它方法即可。
?另外說明一下,為了防止和減少因DB連接未及時釋放導(dǎo)致的連接池不足等原因,故默認執(zhí)行所有的CRUD方法都是用完即釋放,但有一種情況不會釋放就是使用了事務(wù),若使用事務(wù),則必需配套使用:UseDbTransaction、Commit、或失敗執(zhí)行Rollback,否則可能導(dǎo)致未能及時釋放對象,當(dāng)然最終當(dāng)SqlDapperUtil實例被回收后事務(wù)若沒有提交或回滾,會強制執(zhí)行回滾操作并釋放事務(wù)及連接對象,防止可能的資源浪費情況。
本來早就想總結(jié)一下這篇文章,但一直由于工作太忙沒有時間,今天利用加班研究.NET CORE的空隙時間完成,請大家支持,有好東西我一定會分享的,雖然不一定高大上,但一定實用且項目中有實戰(zhàn)過的。
轉(zhuǎn)載于:https://www.cnblogs.com/zuowj/p/9570956.html
總結(jié)
以上是生活随笔為你收集整理的基于Dapper二次封装了一个易用的ORM工具类:SqlDapperUtil的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在eclipse中安装与配置maven环
- 下一篇: BZOJ3944: Sum