1. 程式人生 > >EF臨時表批量插入

EF臨時表批量插入

1.概述

1.1 背景

使用EF框架對大量資料進行的插入或修改時,效能不高。而EF擴充套件庫的批量修改每次只能修改特定的欄位且約束欄位也是特定的,當修改的資料是隨機時,EF擴充套件庫的批量修改滿足我的需求。

1.2 目標

插入大量資料時,為提高效能,使用SqlBulkCopy臨時表批量插入。修改大量資料是,先把修改的資料放到記憶體中,進行修改。然後刪除資料庫的資料,再用臨時表一次插入。

2.解決方案

結合EF框架,使用SqlBulkCopy方法批量插入。

/// <summary>  
        /// 批量插入  
        /// </summary>  
        /// <typeparam name="T">泛型集合的型別</typeparam>  
        /// <param name=" dbContext ">連線物件</param>  
        /// <param name="tableName">將泛型集合插入到本地資料庫表的表名</param>  
        /// <param name="list">要插入大泛型集合</param>  
        public static bool BulkInsert<T>(DbContext dbContext , string tableName, IList<T> list)
        {
            try
            {
                if (list == null || list.Count == 0) return true;
                if (dbContext.Database.Connection.State != ConnectionState.Open)
                {
                    dbContext.Database.Connection.Open(); //開啟Connection連線  
                }
                using (var bulkCopy = new SqlBulkCopy(dbContext.Database.Connection.ConnectionString))
                {
                    bulkCopy.BatchSize = list.Count;
                    bulkCopy.DestinationTableName = tableName;

                    var table = new DataTable();
                    var props = TypeDescriptor.GetProperties(typeof(T))

                        .Cast<PropertyDescriptor>()
                        .Where(propertyInfo => propertyInfo.PropertyType.Namespace.Equals("System"))
                        .ToArray();

                    foreach (var propertyInfo in props)
                    {
                        bulkCopy.ColumnMappings.Add(propertyInfo.Name, propertyInfo.Name);
                        table.Columns.Add(propertyInfo.Name, Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType);
                    }

                    var values = new object[props.Length];
                    foreach (var item in list)
                    {
                        for (var i = 0; i < values.Length; i++)
                        {
                            values[i] = props[i].GetValue(item);
                        }
                        table.Rows.Add(values);
                    }

                    bulkCopy.WriteToServer(table);
                    if (dbContext.Database.Connection.State != ConnectionState.Closed)
                    {
                        dbContext.Database.Connection.Close(); //關閉Connection連線  
                    }
                    return true;
                }
            }
            catch (Exception ex)
            {
                if (dbContext.Database.Connection.State != ConnectionState.Closed)
                {
                    dbContext.Database.Connection.Close(); //關閉Connection連線  
                }
                return false;
            }
     }

呼叫方法如下:

List<Students> lstStu = new List< Students>();

// lstStu.Add(stu);

if (!DbHelper.BulkInsert< Students>( dbContext, "Students", lstTestStu))

{

     return false;

}

3. 解決方案分析

以上方案解決了批量插入的需求。但是要批量修改資料,需要先刪除資料庫資料,然後再批量插入。這個過程需要使用到事務來保證資料的一致性。這裡我使用的是TransactionScope事務。有關TransactionScope使用說明可看“TransactionScope簡介

”。