为了在数据库中插入大量数据,我曾经将所有插入信息收集到列表中并将此列表转换为a DataTable
.然后我通过将该列表插入数据库SqlBulkCopy
.
我发送生成的列表LiMyList
,其中包含我要插入数据库的所有批量数据的信息,并将其
传递给我的批量插入操作
InsertData(LiMyList, "MyTable");
哪里InsertData
是
public static void InsertData(List list,string TableName) { DataTable dt = new DataTable("MyTable"); clsBulkOperation blk = new clsBulkOperation(); dt = ConvertToDataTable(list); ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal); using (SqlBulkCopy bulkcopy = new SqlBulkCopy(ConfigurationManager.ConnectionStrings["SchoolSoulDataEntitiesForReport"].ConnectionString)) { bulkcopy.BulkCopyTimeout = 660; bulkcopy.DestinationTableName = TableName; bulkcopy.WriteToServer(dt); } } public static DataTable ConvertToDataTable (IList 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; }
现在我想做一个更新操作,是否有任何方法可以通过将数据SqlBulkCopy
更新到DataBase从C#.Net 完成插入数据
根据我的个人经验,处理这种情况的最佳方法是使用带有a Table-Valued Parameter
和a 的存储过程User-Defined Table Type
.只需使用数据表的列设置类型,并将所述数据表作为参数传入SQL命令.
在存储过程中,您可以直接连接某个唯一键(如果您要更新的所有行都存在),或者 - 如果您可能遇到必须同时执行更新和插入的情况 - 请使用SQL Merge
命令存储过程以处理适用的更新和插入.
Microsoft既有语法参考,也有一篇包含 Merge 示例的文章.
对于.NET部分,将参数类型SqlDbType.Structured
设置为as 并将所述参数的值设置为包含要更新的记录的数据表是一件简单的事情.
该方法提供了清晰度和易维护性的优点.虽然可能有一些方法可以提供性能改进(例如将其放入临时表中然后遍历该表),但我认为它们被.NET和SQL处理传输表并更新记录本身的简单性所取代.吻
之前我所做的是从数据执行批量插入到临时表,然后使用命令或存储过程来更新临时表与目标表相关的数据.临时表是一个额外的步骤,但与逐行更新数据相比,如果行数很大,则可以通过批量插入和大量更新获得性能提升.
例:
public static void UpdateData<T>(List<T> list,string TableName) { DataTable dt = new DataTable("MyTable"); dt = ConvertToDataTable(list); using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["SchoolSoulDataEntitiesForReport"].ConnectionString)) { using (SqlCommand command = new SqlCommand("", conn)) { try { conn.Open(); //Creating temp table on database command.CommandText = "CREATE TABLE #TmpTable(...)"; command.ExecuteNonQuery(); //Bulk insert into temp table using (SqlBulkCopy bulkcopy = new SqlBulkCopy(conn)) { bulkcopy.BulkCopyTimeout = 660; bulkcopy.DestinationTableName = "#TmpTable"; bulkcopy.WriteToServer(dt); bulkcopy.Close(); } // Updating destination table, and dropping temp table command.CommandTimeout = 300; command.CommandText = "UPDATE T SET ... FROM " + TableName + " T INNER JOIN #TmpTable Temp ON ...; DROP TABLE #TmpTable;"; command.ExecuteNonQuery(); } catch (Exception ex) { // Handle exception properly } finally { conn.Close(); } } } }
请注意,单个连接用于执行整个操作,以便能够在每个步骤中使用临时表,因为临时表的范围是每个连接.