如何在ASP.NET中实现批量更新数据库?
在ASP.NET中,批量更新数据库是一个常见的需求,特别是在处理大量数据时,本文将详细介绍几种在ASP.NET中实现批量更新数据库的方法,包括使用SqlCommandBuilder、SqlBulkCopy以及用户自定义表类型等方法,每种方法都有其优缺点和适用场景,下面将一一介绍。
一、使用SqlCommandBuilder实现批量更新/插入
1. 功能
功能:SqlCommandBuilder可以实现对DataSet在UI层做任意操作后,直接丢给这个方法,该方法可以自动把修改更新到数据库中,而没有必要每次都更新到数据库。
优点:节省代码量,节省时间,这个方法可以代替所有的更新/插入操作语句。
缺点:只能更新一个表,不能更新两个或两个以上相关联的表;表中必须有主键;更新的表中字段不能有image类型的。
2. 使用方法
public int UpdateByDataSet(DataSet ds, string strTblName, string strConnection) { try { using (SqlConnection conn = new SqlConnection(strConnection)) { SqlDataAdapter myAdapter = new SqlDataAdapter(); SqlCommand myCommand = new SqlCommand("select * from " + strTblName, (SqlConnection)this.conn); myAdapter.SelectCommand = myCommand; SqlCommandBuilder myCommandBuilder = new SqlCommandBuilder(myAdapter); myAdapter.Update(ds, strTblName); return 0; } } catch (BusinessException errBU) { throw errBU; } catch (Exception err) { throw new BusinessException(err); } }
说明:用类似下面的语句可以实现批量的插入:System.Data.DataRow dr = ds.Tables[0].NewRow(); dr[0] = "222"; dr[1] = "test"; ds.Tables[0].Rows.Add(dr);
。
注意点:select * from "+strTblName是一定要的,主要是告诉SqlDataAdapter更新哪个表.不过可以用top 1来提高效率(个人认为)
,如果没有myCommandBuilder
那句就会出错,一般是这样的,如果用设计器将SqlDataAdapter拖到页面中使用时,不会出现这种情况,因为系统会自动生成SqlDataAdapter的属性命令, .UpdateCommane insertCommand selectCommand等,但是有些程序员不喜欢用设计器,或者是有些地方没必要拖动SqlDataAdapter这么个庞大物来实现,那么SqlDataAdapter就不会自动生成相关的查询或更新语句了.所以当执行到SqlDataAdapter.Update(ds)语句时,SqlDataAdapter桥接器不知道更新哪个表.不报错了。
二、自己写SqlCommand实现批量更新/插入
1. 功能
功能:在以前版本的ADO.NET中,使用DataSet中的更改来更新数据库时,DataAdapter的Update方法每次更新数据库的一行,因为该方法循环访问指定DataTable中的行,会检查每个DataRow,确定是否已修改,如果该行已修改,将根据该行的RowState属性值调用相应的UpdateCommand、InsertCommand或DeleteCommand,每一次行更新都涉及网络与数据库之间的双向数据传输,在ADO.NET 2.0中,DataAdapter公开了UpdateBatchSize属性,将UpdateBatchSize设置为正整数值将使对数据库的更新以指定大小的批次进行发送,如果将UpdateBatchSize设置为10,会将10个独立的语句组合在一起并作为一批提交,将UpdateBatchSize设置为0将导致DataAdapter使用服务器可以处理的最大批次的大小,如果将其设置为1,则禁用批量更新,因为此时每次发送一行。
优点:灵活性高,可以根据实际需求定制SQL语句。
缺点:需要编写更多的代码,且容易出错。
2. 使用方法
using System; using System.Data; using System.Data.SqlClient; using System.Linq; using System.Text; namespace 批量插入更新数据 { class Program { static void Main(string[] args) { DateTime dt1 = System.DateTime.Now; string connStr = @"server=SHEN\SQL2012;uid=sa;pwd=123456;database=LmhsDB"; using (SqlConnection con = new SqlConnection(connStr)) { con.Open(); SqlTransaction tran = con.BeginTransaction(); try { //批量插入 Inserts(con, tran); Updates(con, tran); tran.Commit(); } catch { tran.Rollback(); } } Console.WriteLine("耗时:" + Convert.ToDouble(ts.TotalMilliseconds / 1000) + "秒"); } public static void Inserts(SqlConnection con, SqlTransaction tran) { DataTable dtIns = new DataTable(); //首先查出一张空表 作为模版(注意主键自增问题:SqlBulkCopyOptions.KeepNulls) SqlCommand sqlIns = new SqlCommand("select ID,UserName,Gender,CreateTime " + " FROM InsertTest where 1=0 ", con, tran); SqlDataAdapter sdaIns = new SqlDataAdapter(); sdaIns.SelectCommand = sqlIns; sdaIns.Fill(dtIns); //插入1000条 for (int i = 0; i < 1000; i++) { DataRow dataRow = dtIns.NewRow(); dataRow[0] = 0; dataRow[1] = "我叫" + Guid.NewGuid(); dataRow[2] = "男"; dataRow[3] = DateTime.Now; dtIns.Rows.Add(dataRow); } using (SqlBulkCopy sqlBulkIns = new SqlBulkCopy(con, SqlBulkCopyOptions.KeepNulls, tran)) { sqlBulkIns.DestinationTableName = "InsertTest"; sqlBulkIns.BatchSize = dtIns.Rows.Count; if (dtIns != null && dtIns.Rows.Count != 0) { sqlBulkIns.WriteToServer(dtIns); } } sqlIns.Dispose(); } public static void Updates(SqlConnection con, SqlTransaction tran) { DataSet ds = new DataSet(); SqlDataAdapter sda = new SqlDataAdapter(); //先查询出一个模版放到DataSet中让更新Dataset中打的数据 然后SqlData SqlCommand sqlUpd = new SqlCommand("select ID,UserName,Gender,CreateTime " + "from UpdateTest where 1=0", con, tran); sda.SelectCommand = sqlUpd; sda.Fill(ds); //修改1000条 for (int i = 0; i < 1000; i++) { DataRow dataRow = ds.Tables[0].NewRow(); dataRow["ID"] = i; dataRow["UserName"] = "我叫" + Guid.NewGuid(); dataRow["Gender"] = "女"; dataRow["CreateTime"] = DateTime.Now; ds.Tables[0].Rows.Add(dataRow); } using (SqlBulkCopy sqlBulkUpd = new SqlBulkCopy(con, SqlBulkCopyOptions.KeepNulls, tran)) { sqlBulkUpd.DestinationTableName = "UpdateTest"; sqlBulkUpd.BatchSize = ds.Tables[0].Rows.Count; if (ds != null && ds.Tables[0].Rows.Count != 0) { sqlBulkUpd.WriteToServer(ds); } } sqlUpd.Dispose(); } } }
注意点:执行非常大的批次可能会降低性能,在实现应用程序之前,应测试最佳的批次大小设置。
三、用户自定义表类型实现批量导入(性能最优)
1. 功能
功能:用户自定义表类型是一种非常高效的批量导入方式,可以将大量的数据一次性导入到数据库中,这种方式的性能通常比其他方式要好很多。
优点:性能最优,适合大数据量的导入。
缺点:需要创建用户自定义表类型,稍微复杂一些。
2. 使用方法
-创建用户自定义表类型 CREATE TYPE [dbo].[MyTableType] AS TABLE( [Column1] [int] NOT NULL, [Column2] [varchar](50) NOT NULL, ... -其他列定义 ) GO -使用用户自定义表类型进行批量插入 DECLARE @MyTable [dbo].[MyTableType]; INSERT INTO @MyTable (Column1, Column2) VALUES (Value1, Value2), ...; -多行数据插入 EXEC sp_executesql N'INSERT INTO MyTable (Column1, Column2) SELECT Column1, Column2 FROM @MyTable', N'@MyTable [dbo].[MyTableType]', @MyTable = @MyTable;
注意点:在使用用户自定义表类型时,需要注意数据的完整性和一致性问题,由于涉及到多个步骤的操作,因此在事务控制方面也需要特别注意。
四、SqlBulkCopy实现批量插入数据(性能优)
1. 功能
功能:SqlBulkCopy类提供了一种简单高效的方法来将数据从源数据源批量***到目的地数据源,它非常适合于大批量数据的导入操作。
优点:性能优,操作简单。
缺点:只支持插入操作,不支持更新操作。
2. 使用方法
using System; using System.Data; using System.Data.SqlClient; using System.Linq; using System.Text; namespace 批量插入更新数据 { class Program { static void Main(string[] args) { DateTime dt1 = System.DateTime.Now; string connStr = @"server=SHEN\SQL2012;uid=sa;pwd=123456;database=LmhsDB"; using (SqlConnection con = new SqlConnection(connStr)) { con.Open(); SqlTransaction tran = con.BeginTransaction(); try { //批量插入 Inserts(con, tran); Updates(con, tran); tran.Commit(); } catch { tran.Rollback(); } } Console.WriteLine("耗时:" + Convert.ToDouble(ts.TotalMilliseconds / 1000) + "秒"); } public static void Inserts(SqlConnection con, SqlTransaction tran) { DataTable dtIns = new DataTable(); //首先查出一张空表 作为模版(注意主键自增问题:SqlBulkCopyOptions.KeepNulls) SqlCommand sqlIns = new SqlCommand("select ID,UserName,Gender,CreateTime " + " FROM InsertTest where 1=0 ", con, tran); SqlDataAdapter sdaIns = new SqlDataAdapter(); sdaIns.SelectCommand = sqlIns; sdaIns.Fill(dtIns); //插入1000条 for (int i = 0; i < 1000; i++) { DataRow dataRow = dtIns.NewRow(); dataRow[0] = 0; dataRow[1] = "我叫" + Guid.NewGuid(); dataRow[2] = "男"; dataRow[3] = DateTime.Now; dtIns.Rows.Add(dataRow); } using (SqlBulkCopy sqlBulkIns = new SqlBulkCopy(con, SqlBulkCopyOptions.KeepNulls, tran)) { sqlBulkIns.DestinationTableName = "InsertTest"; sqlBulkIns.BatchSize = dtIns.Rows.Count; if (dtIns != null && dtIns.Rows.Count != 0) { sqlBulkIns.WriteToServer(dtIns); } } sqlIns.Dispose(); } } }
小伙伴们,上文介绍了“asp.net 批量更新数据库”的内容,你了解清楚吗?希望对你有所帮助,任何问题可以给我留言,让我们下期再见吧。