[.NET]輕量又兼具效能的ORM Framework - Dapper

  • 10164
  • 0
  • .NET
  • 2016-06-18

[.NET]輕量又兼具效能的ORM Framework - Dapper

最近再處理物件和資料對應效能問題,

同時改寫自己的Code Generation小工具,

在找如何提高ORM效能的方法時,

讓我無意見發現這套強大的ORM Framework - Dapper 。

我看網頁上所寫的效能真的有讓我嚇到,

讀取速度快接近IDataReader( 我 實測Dapper 後,發現更快),

但我真正在意的是物件和資料對應效能問題,

我大概去追了一下 Dapper 在處理序列化所使用的方法,

發現它使用  ILGenerator.Emit Method 來快速產生object (Reflection IDataReader ),

就連Linq 2 SQL CompiledQuery 效能都沒 Dapper 來的屌,

而且這各Dapper.dll只有小小的59KB,使用方法也很簡單。

經過自己實測50000筆資料對應,真的要給 Dapper Mapping 大大一個讚,

下面是測試結果和程式碼。

 

 

使用 Dapper

 


string connstr = ConfigurationManager.ConnectionStrings["Develop"].ToString();
            string sql = @"select top(50000) * from AP_LOG";
            string mycount = string.Empty;
            Stopwatch sw = new Stopwatch();
            sw.Reset();
            using (SqlConnection connection = new SqlConnection(connstr))
            {
                // using Dapper
                sw.Start();
                var myquery = connection.Query<AP_LOG>(sql, null);                
                sw.Stop();
                Console.WriteLine("筆數:{0},時間(ms):{1}", myquery.Count().ToString(), sw.ElapsedMilliseconds.ToString());
                Console.ReadLine();
            }

 

 

第一次

image

 

第二次

image

 

第三次

image

 

 

使用自定義RowMapping Method(Reflection IDataReader)


string connstr = ConfigurationManager.ConnectionStrings["Develop"].ToString();
            string sql = @"select top(50000) * from AP_LOG";
            string mycount = string.Empty;
            Stopwatch sw = new Stopwatch();
            sw.Reset();
            using (SqlConnection connection = new SqlConnection(connstr))
            {
                // using Dapper
                //sw.Start();
                //var myquery = connection.Query<AP_LOG>(sql, null);                
                //sw.Stop();
                //Console.WriteLine("筆數:{0},時間(ms):{1}", myquery.Count().ToString(), sw.ElapsedMilliseconds.ToString());
                //Console.ReadLine();
                
                // using custom mapping
                connection.Open();
                using (SqlCommand command = new SqlCommand(sql, connection))
                {
                    sw.Start();
                    SqlDataReader dr = command.ExecuteReader();
                    mycount = RowMapping(dr);
                    sw.Stop();
                }
                Console.WriteLine("筆數:{0},時間(ms):{1}", mycount.ToString(), sw.ElapsedMilliseconds.ToString());
                Console.ReadLine();
            }

 


private static string RowMapping(IDataReader dr)
        {
            List<AP_LOG> ap_logs = new List<AP_LOG>();
            while (dr.Read())
            {
                AP_LOG ap_log = new AP_LOG();
                for (int i = 0; i < dr.FieldCount; i++)
                {
                    PropertyInfo property = ap_log.GetType().GetProperty(dr.GetName(i));
                    property.SetValue(ap_log, dr.IsDBNull(i) ? "null" : dr.GetValue(i), null);                
                }
                ap_logs.Add(ap_log);            
            }
            return ap_logs.Count.ToString(); 
        }

 

 

第一次

image

 

第二次

image

 

第三次

image

 

結果

方法 平均時間(ms)
Dapper 988
自定義RowMapping 1991

 

測試完後,看來自己套用 Dapper 是無法避免的(個人.NET等級無法和 Dapper 相比...哀),

有種相見恨晚的感覺阿

 

參考

dapper-dot-net