不知道博客怎么去写去排版,查了好多相关博客,也根据本身作过项目总结,正好最近搭个微服务框架,顺便把搭建微服务框架所运用的知识都进行博客梳理,为了之后复习,就仔细琢磨写一下本身在微服务框架中对Dapepr的理解以及项目中应用。 dapper 只是一个代码文件,彻底开源,你能够在项目里任何位置,来实现数据到对象ORM操做(固然先引用Dapper文件),体积小速度快。使用好处增删改查比较快,不用本身写sql,由于这都是重复技术含量低的工做,还有程序中大量的数据库中读取数据而后建立model,而且为model字段赋值,这都是很轻松的,我的认为Dapper能够看作HelpSQL,甚至比HelperSQL性能高一点。若是你喜欢原生的SQL,那么有喜欢ORM的简单,那你必定钟情于Dapper 而且爱上他。mysql
1、Dapper是一个轻量级ORM类,代码就是一个SQLMapper.cs文件,编译后通常在40k左右的dll; 2、Dapper快,为啥说快呢?由于Dapepr速度接近IDataReader,取列表的数据超过DataTable; 3、Dapper支持什么数据库?支持Mysql,sqlLite,SQLServer,Oracle等一系列数据库,(备注:我我的在在作demo中,就是使用了Mysql,SQLServer,公司和个电脑装的数据库不同,就都测试了); 4、Dapper的R支持多表并联的对象,支持一对多,多对多关系,而且没侵入性,想用就用 ; 5、Dapper原理就是经过Emit反射IDateReader的队列,来快速获得和产生对象;这也是性能高的缘由之一; 6、Dapper语法简单,快速入手。
若是面试,让你说出Dapper的好处,为啥用Dapper,上面回答出来,杠杠的。。。。。。。。
面试官:我靠,小伙子懂的挺多.........
在超过500次poco serialization的过程当中所表现的性能,咱们发现dapper是第二名,固然第一名谁也没法超越,越底层的固然久越快,同时也就越麻烦。web
在NuGet中引用Dapper面试
新建一个ConnectionFactory类,建立连接对象,這里咱们封装两个方法分别获取SQLServerr 和MySQLsql
public class ConnectionFactory { //获取web 中的配置文件 private static readonly string QlwMysqlConnection = ConfigurationManager.AppSettings["sqlconnectionString"]; /// <summary> /// sqlServer 数据库 /// </summary> /// <returns></returns> public static IDbConnection SqlServerConnection() { string sqlconnectionString = QlwMysqlConnection; //ConfigurationManager.ConnectionStrings["sqlconnectionString"].ToString(); var connection = new SqlConnection(sqlconnectionString); if (connection.State == ConnectionState.Closed) { connection.Open(); } return connection; } /// <summary> /// mySQl 数据库 /// </summary> /// <returns></returns> public static IDbConnection MySqlConnection() { string mysqlconnectionString = QlwMysqlConnection; //ConfigurationManager.ConnectionStrings["mysqlconnectionString"].ToString(); var connection = new MySqlConnection(mysqlconnectionString); if (connection.State == ConnectionState.Closed) { connection.Open(); } return connection; } }
(1)先看一下后台:SqlMapper,封装了给咱们提供了那些方法:数据库
(2)咱们根据上面方法加一层,简单封装,为了业务更加方便:app
先说说添加Insert操做,咱们对Execute方法进行简单的封装:框架
SqlMapper提供:两个封装Execute:微服务
(3)、建立一个DapperDBContext类性能
public static class DapperDBContext { public static List<T> AsList<T>(this IEnumerable<T> source) { if (source != null && !(source is List<T>)) return source.ToList(); return (List<T>)source; } //参数咱们跟后台封装方法保持一致 public static int Execute(string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null, int databaseOption = 1) { using (var conn = ConnectionFactory.MySqlConnection()) { var info = "SQL语句:" + sql + " \n SQL参数: " + JsonConvert.SerializeObject(param) + " \n"; // LogHelper.ErrorLog(info); // 能够记录操做 var sw = new Stopwatch(); sw.Start(); var restult = conn.Execute(sql, param, transaction, commandTimeout, commandType); sw.Stop(); LogHelper.ErrorLog(info + "耗时:" + sw.ElapsedMilliseconds + (sw.ElapsedMilliseconds > 1000 ? "#####" : string.Empty) + "\n"); // 能够记录操做 return restult; } } public static int Execute(CommandDefinition command, int databaseOption = 1) { using (var conn = ConnectionFactory.MySqlConnection()) { var info = " SQL语句:" + command.CommandText + " \n SQL命令类型: " + command.CommandType + " \n"; // LogHelper.Info(info);// 能够记录操做 var sw = new Stopwatch(); sw.Start(); var restult = conn.Execute(command); sw.Stop(); // LogHelper.Info(info + "耗时:" + sw.ElapsedMilliseconds + (sw.ElapsedMilliseconds > 1000 ? "#####" : string.Empty) + "\n");// 能够记录操做 return restult; } } }
public class DepartmentRepository { /// <summary> /// 插入单条数据以及多条数据 /// </summary> /// <param name="department"></param> /// <returns></returns> public bool Add(List<Department> department, AuthResources authResources) { #region 插入单条数据 string sql = @" INSERT INTO Department (ID,EID,Name,Remarks,Description,Notice,ParentId,AddTime,IsDel,UpdateTime)
VALUES(@ID,@EID,@Name,@Remarks,@Description,@Notice,@ParentId,@AddTime,@IsDel,@UpdateTime); "; var result = DapperDBContext.Execute(sql, department[0]); return result >= 1; #endregion } }
// department是100条数据
public bool Add(List<Department> department, AuthResources authResources) { #region 插入单条数据 string sql = @" INSERT INTO Department (ID,EID,Name,Remarks,Description,Notice,ParentId,AddTime,IsDel,UpdateTime)
VALUES(@ID,@EID,@Name,@Remarks,@Description,@Notice,@ParentId,@AddTime,@IsDel,@UpdateTime); "; var result = DapperDBContext.Execute(sql, department); //直接传送list对象 return result >= 1; #endregion }
這里咱们采用事物,事物自己有两个特有特性:原子性和统一性,好比:向ABC三个表同时插入,只要有个插入有误都失败,若是不采用事物,采用纯sql插入可能出现数据不一致,AB成功,C失败 。学习
那咱们在DapperDBContext中继续封装一个事物的方法,不知道你如今有没有体会到,咱们为啥在中间一层,为了咱们根据业务的扩展而却要。
方法能够本身扩展,根据本身业务须要去延伸。。。。。
/// <summary> /// 多表操做--事务 /// </summary> /// <param name="trans"></param> /// <param name="databaseOption"></param> /// <param name="commandTimeout"></param> /// <returns></returns> public static Tuple<bool, string> ExecuteTransaction(List<Tuple<string, object>> trans, int databaseOption = 1, int? commandTimeout = null) { if (!trans.Any()) return new Tuple<bool, string>(false, "执行事务SQL语句不能为空!"); using (var conn = ConnectionFactory.MySqlConnection()) { //开启事务 using (var transaction = conn.BeginTransaction()) { try { var sb = new StringBuilder("ExecuteTransaction 事务: "); foreach (var tran in trans) { sb.Append("SQL语句:" + tran.Item1 + " \n SQL参数: " + JsonConvert.SerializeObject(tran.Item2) + " \n"); // 根据业务添加纪录日志 LogHelper.InfoLog("SQL语句:" + tran.Item1 + " \n SQL参数: " +
JsonConvert.SerializeObject(tran.Item2) + " \n"); //执行事务 conn.Execute(tran.Item1, tran.Item2, transaction, commandTimeout); } var sw = new Stopwatch(); sw.Start(); //提交事务 transaction.Commit(); sw.Stop(); // 根据业务添加纪录日志 LogHelper.InfoLog(sb.ToString() + "耗时:" + sw.ElapsedMilliseconds + (sw.ElapsedMilliseconds > 1000 ?
"#####" : string.Empty) + "\n"); return new Tuple<bool, string>(true, string.Empty); } catch (Exception ex) { //todo:!!!transaction rollback can not work. LogHelper.ErrorLog(ex); //回滚事务 transaction.Rollback(); conn.Close(); conn.Dispose(); return new Tuple<bool, string>(false, ex.ToString()); } finally { conn.Close(); conn.Dispose(); } } } }
方法中用到的Tuple(元组)方法咱们就不作介绍,后期我会整理一篇专门介绍元组的方法以及一些新的特性。事物一样能够知足一个表多条数据插入
public bool Add(List<Department> department, AuthResources authResources) { #region 事务:元组形式插入多条数据 var param = new List<Tuple<string, object>>(); Tuple<string, object> tupel; var sw = new Stopwatch(); sw.Start(); for (int i = 0; i < 100; i++) { tupel = new Tuple<string, object>(@" INSERT INTO Department (ID,EID,Name,Remarks,Description,Notice,ParentId,AddTime,IsDel,UpdateTime) VALUES(@ID,@EID,@Name,@Remarks,@Description,@Notice,@ParentId,@AddTime,@IsDel,@UpdateTime) ", new { ID = Guid.NewGuid(), EID = Guid.NewGuid(), Name = "部门", Remarks = "", Description = "", AddTime = DateTime.Now, IsDel = 0, UpdateTime = DateTime.Now, ParentId = Guid.NewGuid(), Notice = "", }); param.Add(tupel); } tupel = new Tuple<string, object>(@" INSERT INTO AuthResources (ID,EID,AuthId,ResourceId,AddTime,IsDel,UpdateTime) VALUES(@ID,@EID,@AuthId,@ResourceId,@AddTime,@IsDel,@UpdateTime) ", new { ID = Guid.NewGuid(), EId = Guid.NewGuid(), AuthId = Guid.NewGuid(), ResourceId = Guid.NewGuid(), AddTime = DateTime.Now, IsDel = 0, UpdateTime = DateTime.Now, }); param.Add(tupel);
//调用上面咱们封装的事物方法:ExecuteTransaction var result = DapperDBContext.ExecuteTransaction(param).Item1; sw.Stop(); return result; #endregion }
结果:
总结:(Dapper 还没结束,下篇正在书写中。。。。。。。)
一、插入的三种方式就结束了,若是你有更好的方法,欢迎下方留言,一块儿讨论,本文有不对的方法也多多指出;
二、在作的过程当中,还百度相关资料,无心中发现数据遍历能够不用for和foreach,
能够用 Enumerable.Range,已测试性能,很不错,Dapper写完创建新的博客讲解。。。。
手动写东西,你会发现好多问题,你们一块儿边学习边总结,虽然写博客很费事,可是确实能收入很多东西,最起码你写的获得别人承认,
看得懂,若是还能推荐一下,心理满满的小激动,哈哈哈哈,比如:你学外语,不去跟别人说,沟通,怎么知道学的怎么样,博客园就是這个平台.........