SqlServer使用SqlBulkCopy批量插入/更新数据

#region 自己扩展的方法

        /// <summary>
        /// 批量插入数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        public void BatchInsert<T>(List<T> list)
        {
            if (list.Any())
            {
                var pdco = PocoData.ForType(list.FirstOrDefault().GetType(), _defaultMapper);
                string tableName = pdco.TableInfo.TableName;
                using (SqlConnection conn = new SqlConnection(_connectionString))
                {
                    try
                    {
                        conn.Open();
                        //创建属性的集合    
                        List<PropertyInfo> pList = new List<PropertyInfo>();
                        //获得反射的入口    
                        Type type = typeof(T);
                        DataTable dt = new DataTable();
                        dt = ConvertToDataTable(list);
                        using (SqlBulkCopy bulkCopy = new SqlBulkCopy(conn))
                        {
                            bulkCopy.DestinationTableName = tableName;
                            bulkCopy.BatchSize = list.Count;
                            if (dt != null && dt.Rows.Count != 0)
                            {
                                bulkCopy.WriteToServer(dt);
                            }
                            bulkCopy.Close();
                        }
                    }
                    catch (Exception e)
                    {
                        throw e;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
            }
        }

        /// <summary>
        /// 批量更新数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        public void BatchUpdate<T>(List<T> list)
        {
            if (list.Any())
            {
                BatchUpdate(list, null, null);
            }
        }

        /// <summary>
        /// 批量更新数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list">实体集合</param>
        /// <param name="columns">需要更新哪些列,为null是更新所有列</param>
        /// <param name="onRelations">跟新条件,默认是主键,多个条件关系是并列的and</param>
        public void BatchUpdate<T>(List<T> list, IEnumerable<string> columns, Dictionary<string, string> onRelations)
        {
            var sbUpdateColumns = new StringBuilder();
            var sbOnRelation = new StringBuilder();
            var pdco = PocoData.ForType(list.FirstOrDefault().GetType(), _defaultMapper);
            var dt = new DataTable();
            var tableName = pdco.TableInfo.TableName;
            var columnsIndex = 0;
            var onRelationIndex = 0;

            //构建需要更新的列
            if (columns == null)
            {
                foreach (var i in pdco.Columns)
                {
                    if (i.Key.ToLower() != pdco.TableInfo.PrimaryKey.ToLower())
                    {
                        // Build the sql
                        if (columnsIndex > 0)
                            sbUpdateColumns.Append(", ");
                        sbUpdateColumns.AppendFormat("T.{0} = Temp.{0}", i.Key);
                        columnsIndex++;
                    }
                }
            }
            else
            {
                foreach (var colname in columns)
                {
                    var pc = pdco.Columns[colname];

                    // Build the sql
                    if (columnsIndex > 0)
                        sbUpdateColumns.Append(", ");
                    sbUpdateColumns.AppendFormat("T.{0} = Temp.{0}", colname);
                    columnsIndex++;
                }
            }

            //构建更新条件
            if (onRelations == null)
            {

                sbOnRelation.AppendFormat("T.{0} = Temp.{1}", pdco.TableInfo.PrimaryKey, pdco.TableInfo.PrimaryKey);
            }
            else
            {
                foreach (var onRelation in onRelations)
                {
                    if (onRelationIndex > 0)
                        sbOnRelation.Append(" AND ");
                    sbOnRelation.AppendFormat("T.{0} = Temp.{1}", onRelation.Key, onRelation.Value);
                    onRelationIndex++;
                }
            }

            using (SqlConnection conn = new SqlConnection(_connectionString))
            {
                using (SqlCommand command = new SqlCommand("", conn))
                {
                    try
                    {
                        conn.Open();
                        var tempTableName = $"Temp{DateTime.Now.ToString("yyyMMddHHmmss")}";

                        //构建临时表
                        command.CommandText = $"SELECT * INTO {tempTableName} FROM {tableName} WHERE 1 = 2;";
                        command.ExecuteNonQuery();

                        //插入临时表
                        dt = ConvertToDataTable(list);
                        using (SqlBulkCopy bulkCopy = new SqlBulkCopy(_connectionString, SqlBulkCopyOptions.KeepIdentity))
                        {
                            bulkCopy.DestinationTableName = tempTableName;
                            bulkCopy.BatchSize = list.Count;
                            if (dt != null && dt.Rows.Count != 0)
                            {
                                bulkCopy.WriteToServer(dt);
                                bulkCopy.Close();
                            }
                        }

                        //从临时表更新到原表,并删除临时表
                        command.CommandTimeout = 300;
                        command.CommandText = $"UPDATE T SET {sbUpdateColumns.ToString()} FROM {_provider.EscapeTableName(tableName)} T INNER JOIN {tempTableName} Temp ON {sbOnRelation.ToString()}; DROP TABLE {tempTableName};";
                        command.ExecuteNonQuery();
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                    finally
                    {
                        conn.Close();
                    }
                }
            }
        }

        /// <summary>
        /// 类集合转为DataTable
        /// </summary>
        public static DataTable ConvertToDataTable<T>(IList<T> data)
        {
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
            DataTable table = new DataTable();
            foreach (PropertyDescriptor prop in properties)
                table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
            foreach (T item in data)
            {
                DataRow row = table.NewRow();
                foreach (PropertyDescriptor prop in properties)
                    row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
                table.Rows.Add(row);
            }
            return table;
        }

        #endregion
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值