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

Dapper介紹

 簡介:

     不知道博客怎麼去寫去排版,查了好多相關博客,也根據本身作過項目總結,正好最近搭個微服務框架,順便把搭建微服務框架所運用的知識都進行博客梳理,爲了之後複習,就仔細琢磨寫一下本身在微服務框架中對Dapepr的理解以及項目中應用。  dapper 只是一個代碼文件,徹底開源,你能夠在項目裏任何位置,來實現數據到對象ORM操做(固然先引用Dapper文件),體積小速度快。使用好處增刪改查比較快,不用本身寫sql,由於這都是重複技術含量低的工做,還有程序中大量的數據庫中讀取數據而後建立model,而且爲model字段賦值,這都是很輕鬆的,我的認爲Dapper能夠看作HelpSQL,甚至比HelperSQL性能高一點。若是你喜歡原生的SQL,那麼有喜歡ORM的簡單,那你必定鍾情於Dapper 而且愛上他。mysql

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是第二名,固然第一名誰也沒法超越,越底層的固然久越快,同時也就越麻煩。web

 

Dapper代碼應用

第一步:

在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;
            }
        }
}

(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 } }

(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 }

 

(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 還沒結束,下篇正在書寫中。。。。。。。)

      一、插入的三種方式就結束了,若是你有更好的方法,歡迎下方留言,一塊兒討論,本文有不對的方法也多多指出;

      二、在作的過程當中,還百度相關資料,無心中發現數據遍歷能夠不用for和foreach,

      能夠用 Enumerable.Range,已測試性能,很不錯,Dapper寫完創建新的博客講解。。。。

      手動寫東西,你會發現好多問題,你們一塊兒邊學習邊總結,雖然寫博客很費事,可是確實能收入很多東西,最起碼你寫的獲得別人承認,

      看得懂,若是還能推薦一下,心理滿滿的小激動,哈哈哈哈,比如:你學外語,不去跟別人說,溝通,怎麼知道學的怎麼樣,博客園就是這個平臺.........

  • 博主是利用讀書、參考、引用、抄襲、複製和粘貼等多種方式打形成本身的純鍍 24k 文章,請原諒博主成爲一個無恥的文檔搬運工!
  • 小弟剛邁入博客編寫,文中若有不對,歡迎用板磚扶正,但願給你有所幫助。
相關文章
相關標籤/搜索