Dapper系列之一:Dapper的入门(多表批量插入)

摘要:
Dapper只是一个完全开源的代码文件。您可以在项目中的任何位置实现数据到对象ORM操作,其大小小,速度快。Dapper的优点:1。Dapper是一个轻量级ORM类。该代码是一个SQLMapper.cs文件,编译后通常约为40k dll;2.Dapper,快点,你为什么说得快?因为Dapper的速度接近IDataReader,所以列表的数据比DataTable多;3.Dapper支持哪些数据库?如果你有面试,让你说出Dapper的好处以及为什么使用Dapper。上面的答案是杠杆。。。。。。。。
Dapper介绍 简介:

     不知道博客怎么去写去排版,查了好多相关博客,也根据自己做过项目总结,正好最近搭个微服务框架,顺便把搭建微服务框架所运用的知识都进行博客梳理,为了以后复习,就仔细琢磨写一下自己在微服务框架中对Dapepr的理解以及项目中应用。  dapper 只是一个代码文件,完全开源,你可以在项目里任何位置,来实现数据到对象ORM操作(当然先引用Dapper文件),体积小速度快。使用好处增删改查比较快,不用自己写sql,因为这都是重复技术含量低的工作,还有程序中大量的数据库中读取数据然后创建model,并且为model字段赋值,这都是很轻松的,个人认为Dapper可以看做HelpSQL,甚至比HelperSQL性能高一点。如果你喜欢原生的SQL,那么有喜欢ORM的简单,那你一定钟情于Dapper 并且爱上他。

Dapper的优势:
复制代码
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是第二名,当然第一名谁也无法超越,越底层的当然久越快,同时也就越麻烦。

Dapper系列之一:Dapper的入门(多表批量插入)第3张

Dapper代码应用

第一步:

在NuGet中引用Dapper

Dapper系列之一:Dapper的入门(多表批量插入)第4张

Dapper系列之一:Dapper的入门(多表批量插入)第5张

第二步:

新建一个ConnectionFactory类,创建链接对象,這里我们封装两个方法分别获取SQLServerr 和MySQL

复制代码
 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,封装了给我们提供了那些方法:

Dapper系列之一:Dapper的入门(多表批量插入)第8张

(2)我们根据上面方法加一层,简单封装,为了业务更加方便:

         先说说添加Insert操作,我们对Execute方法进行简单的封装:

           SqlMapper提供:两个封装Execute:

Dapper系列之一:Dapper的入门(多表批量插入)第9张

   (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;
            }
        }
}
复制代码

(4.1)、单条数据插入:

复制代码
 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 } }
复制代码

Dapper系列之一:Dapper的入门(多表批量插入)第14张

(4.2)、单表批量数据插入:

复制代码
           // 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 }
复制代码

Dapper系列之一:Dapper的入门(多表批量插入)第17张

(4.3)、多表多数据批量插入:

     這里我们采用事物,事物本身有两个特有特性:原子性和统一性,比如:向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系列之一:Dapper的入门(多表批量插入)第22张

总结:(Dapper 还没结束,下篇正在书写中。。。。。。。)

      1、插入的三种方式就结束了,如果你有更好的方法,欢迎下方留言,一起讨论,本文有不对的方法也多多指出;

      2、在做的过程中,还百度相关资料,无意中发现数据遍历可以不用for和foreach,

      可以用 Enumerable.Range,已测试性能,很不错,Dapper写完建立新的博客讲解。。。。

      手动写东西,你会发现好多问题,大家一起边学习边总结,虽然写博客很费事,但是确实能收入不少东西,最起码你写的得到别人认可,

      看得懂,如果还能推荐一下,心理满满的小激动,哈哈哈哈,好比:你学外语,不去跟别人说,沟通,怎么知道学的怎么样,博客园就是這个平台.........

  • 博主是利用读书、参考、引用、抄袭、复制和粘贴等多种方式打造成自己的纯镀 24k 文章,请原谅博主成为一个无耻的文档搬运工!
  • 小弟刚迈入博客编写,文中如有不对,欢迎用板砖扶正,希望给你有所帮助。

免责声明:文章转载自《Dapper系列之一:Dapper的入门(多表批量插入)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Ubuntu 下查看CPU 信息命令Qt 调用本地浏览器打开URL下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

.net 中dapper实现事务的三种方式总结

.net 中实现事务查询的三种方式 1.TransactionScope  通过创建TransactionScope  对象然后包裹connection对象执行相关查询操作,完成    此种方式可以用于分布式事务操作,当链接不同数据库时,通过简单配置可以实现不同数据库的事务操作,当使用单机查询时(即只有一个数据库并且与应用服务器在同一台电脑时,不需要做额外...

Dapper扩展之~~~Dapper.Contrib

平台之大势何人能挡? 带着你的Net飞奔吧!http://www.cnblogs.com/dunitian/p/4822808.html#skill 上一篇文章:Dapper逆天入门~强类型,动态类型,多映射,多返回值,增删改查+存储过程+事物案例演示  官方地址:https://github.com/StackExchange/dapper-dot-ne...

Dapper的数据库连接管理(打开、关闭)

  Dapper对于数据库连接的管理:如果已经打开,它会关闭连接。如果你只是做一个快速查询-让Dopter自己处理它。   如果你做了很多事情,你应该自己打开连接,并在最后关闭连接,所有的查询在中…只是从效率的角度来看。 bool wasClosed = cnn.State == ConnectionState.Closed; using (var cmd...

Dapper基本用法--MySql

NuGet: Dapper 2.0.35 MySql.Data System.Data 实体(Entity) 1 public class student 2 { 3 public int Id { get; set; } 4 public string RealName { get; set; } 5...

最火的.NET开源项目(转)

最火的.NET开源项目(转) 综合类 微软企业库微软官方出品,是为了协助开发商解决企业级应用开发过程中所面临的一系列共性的问题, 如安全(Security)、日志(Logging)、数据访问(Data Access)、配置管理(Configuration Manage)等,并将这些广泛使用的应用程序块集成封装至一个叫企业库的程序包中 CommonLi...

dapper 注意事项之GUID

今天把ef框架换成了dapper,数据库使用的是mysql. 主键使用GUID,mysql数据库中设置的为varchar(36). 使用dapper报错,不能将string转换为GUID,后来调试比对发现,mysql中要使用GUID,必须设置为char(36)不能设置为varchar(36)....