SqlServer批量插入数据方法--SqlBulkCopy
来源:互联网 发布:cst仿真软件破解版 编辑:程序博客网 时间:2024/06/05 11:22
最近项目需要插入大量数据,想了一些方法,但是都是低效率、很危险的方法,又在网上找了一些解决方案,自己总结一下,于是有了此文。
1.一条Insert多次请求:sqlcmd.ExecuteNoQuery封装的方法多次调用。
短时间内请求多次,创建多个数据库连接,造成应用连接池堵塞、数据重复等问题。一旦数据量大,对服务器和数据库造成不可想象来说,简直就是灾难,首先排除。
2.多条Insert一次请求:insert into table1 values();insert into table1 values()。
虽然只有一次请求,只有一个数据库连接,但是分条插入会严重拖慢速度,性能也会受到返回计数的影响。对服务器要求很高,要不断的拼接insert语句,也不可取。
3.一条Insert一次请求:insert into table1 values(),(),(),()。SqlServer 2008开始支持
虽然只有一次请求,只有一个数据库连接,也只有一个返回计数,但是因为插入原理和方法2一样,所以效率也会很慢。
4.SqlBulkCopy:.net 2.0时代开始支持,所以SqlServer 2005 完全支持此方法。
推荐此方法,因为它的效率较之前的3个方法提高了5倍左右,且资源占用的不多,原理是先将数据放入内存中的虚拟表DataTable中,再将整张表放入数据库的数据表。使用方法在下文说明。
5.表值参数:SqlServer 2008开始支持表值参数,技术难度较高,因为时间紧迫,没有做过多了解。待日后了解并实现、测试后再做更新。
这里我只用了SqlBulkCopy的一种用法,还有其他用法待日后用到时再做更新,例如:新、旧数据库数据迁移。
这里我给SqlBulkCopy的数据源是DataTable,然而因为数据源的数据不是从别的数据表中读出的,而是json传递的,所以在插入数据之前要先做一个操作,就是生成DataTable。
下面是代码
1.生成DataTable
下面是生成DataTable的公用代码,虽然不是最高效的,但是是我能想到的写法:
/// <summary>/// 根据不同的字段名、数据类型、字段值生成DataTable/// </summary>/// <param name="tblName">要插入的数据库中的表名</param>/// <param name="identity">第一列是否为自增长(一般设计表时都有一个自增长的ID标识列)</param>/// <param name="seed">自增长起始值</param>/// <param name="step">增长长度</param>/// <param name="cellNameType">每一列的名称和数据类型</param>/// <param name="valueList">每一列的名称和值</param>/// <returns></returns>public static DataTable GetDataTable(string tblName, bool identity, int seed, int step, Dictionary<string, string> cellNameType, List<Dictionary<string, string>> valueList){ //这个数据表的名字要和数据库中一致 DataTable dt = new DataTable(tblName); DataColumn dc = null; foreach (var item in cellNameType) { //根据字典添加列 dc = dt.Columns.Add(item.Key, Type.GetType(cellNameType[item.Key])); } //如果第一列是自增长标识列 if (identity) { dt.Columns[0].AutoIncrement = identity;//设置为自动增加 dt.Columns[0].AutoIncrementSeed = seed;//设置起始为1 dt.Columns[0].AutoIncrementStep = step;//设置步长为1 dt.Columns[0].AllowDBNull = false; //设置不允许为空 } DataRow dr; foreach (Dictionary<string, string> dic in valueList) { dr = dt.NewRow();//新增一行 foreach (var item in dic) { //对应列名给列赋值 dr[item.Key] = dic[item.Key]; } dt.Rows.Add(dr); } return dt;}
此方法需要传入的两个特殊的参数,一个是key和value都是string类型的Dictionary字典,key表示列名,value表示数据类型;另一个是字典类型的泛型集合List,这个集合中的字典的key和value也是string类型,key表示列名,value表示列值。在使用此方法时要根据具体数据对这两个参数进行赋值。
2.根据json数据串组织所需GetDataTable()所需参数。
public bool AddList(PayrollModel model, string orderNum){ DataTable dt = new DataTable(); //构造 列名-数据类型 字典 Dictionary<string, string> columns = new Dictionary<string, string>(); columns.Add("salaryId", "System.Int32"); columns.Add("applyId", "System.Int32"); columns.Add("jobId", "System.Int32"); columns.Add("c_userId", "System.Int32"); columns.Add("s_userId", "System.Int32"); columns.Add("orderNum", "System.String"); columns.Add("salaryMoney", "System.Decimal"); columns.Add("giveTime", "System.DateTime"); columns.Add("jobDate", "System.DateTime"); columns.Add("giveType", "System.Int32"); columns.Add("orderState", "System.Int32"); List<Dictionary<string, string>> valueList = new List<Dictionary<string, string>>(); Dictionary<string, string> cellValue; //以下是我根据业务需要构造 列名-列值 字典的泛型集合,这里的列名、顺序要和上文中的列名一致 foreach (SalaryStudentsModel stu in model.students) { foreach (SalaryJobDetailsModel job in stu.jobDetails) { cellValue = new Dictionary<string, string>(); cellValue.Add("applyId", job.applyId.ToString()); cellValue.Add("jobId", model.jobId.ToString()); cellValue.Add("c_userId", model.c_userId.ToString()); cellValue.Add("s_userId", stu.s_userId.ToString()); cellValue.Add("orderNum", orderNum); cellValue.Add("salaryMoney", job.salaryMoney.ToString()); cellValue.Add("giveTime", System.DateTime.Now.ToString()); cellValue.Add("jobDate", job.jobDate.ToString()); cellValue.Add("giveType", "0"); cellValue.Add("orderState", "0"); valueList.Add(cellValue); } } dt = DataTableHandler.GetDataTable("dt_salary", true, 1, 1, columns, valueList); bool flag = false; flag = DataTableToServer(dt, "dt_salary"); return flag;}
完成上文两部分代码,可以生成一个有表头、有数据的虚拟表DataTable,如果数据量巨大,要考虑优化这两部分代码和优化服务器硬件。
3.将DataTable的数据插入数据库
public bool DataTableToServer(DataTable dt, string tblName){ using (SqlConnection con = new SqlConnection(DbHelperSQL.connectionString)) { con.Open(); SqlBulkCopy bulkCopy = new SqlBulkCopy(con); bulkCopy.DestinationTableName = tblName;//要插入的表名,要和数据库中一致 bulkCopy.BatchSize = dt.Rows.Count;//设置提交一次数据要多少行,数据量巨大时可分批提交 bool flag = false; try { if (dt != null && dt.Rows.Count != 0) { bulkCopy.WriteToServer(dt);//写入数据库 flag = true; } } catch (Exception ex) { flag = false; throw ex; } finally { dt = null; con.Close(); if (bulkCopy != null) bulkCopy.Close(); } return flag; }}
此时已将大量数据一次性的放入数据库中,之后就是业务处理,完事儿。
- SqlServer批量插入数据方法--SqlBulkCopy
- SqlBulkCopy批量数据插入
- SqlBulkCopy批量数据插入
- SqlBulkCopy批量插入数据
- SqlBulkCopy批量数据插入
- SqlBulkCopy批量插入数据
- SqlBulkCopy批量插入数据
- SQLBULKCOPY批量插入数据使用
- 批量插入数据 SqlBulkCopy类
- SqlBulkCopy 数据库批量插入数据
- C#批量插入数据SqlBulkCopy
- C# 批量插入表SQLSERVER SqlBulkCopy往数据库中批量插入数据
- DataTable 批量插入SqlServer数据库 使用:SqlBulkCopy
- SqlBulkCopy 快速插入数据到SqlServer 数据库
- 批量插入数据 C# SqlBulkCopy使用
- ADO操控数据库SqlBulkCopy批量数据插入
- 批量插入数据 C# SqlBulkCopy使用
- 批量插入数据 C# SqlBulkCopy使用
- android AndFix热补丁框架(不发版本,修复线上bug)
- Hibernate主键生成策略
- sqlserver字符串拆分(split)方法汇总
- 什么是线程?
- html移动Web开发
- SqlServer批量插入数据方法--SqlBulkCopy
- DSP 与 ARM FPGA 对比分析
- s标签不要嵌套s标签
- CentOS 7 yum安装路径查询方法
- Hibernate标识符属性(主键)生成策略全析
- 九度题目1087约数的个数
- 第4周项目2-太乐了
- POJ 3984迷宫问题(BFS)
- Contiki源码阅读之节点Rime地址