一次插入整个数据表到数据库而不是逐行?

我有一个DataTable,并需要将整个事物推送到数据库表。

我可以用foreach把它全部插入,每次插入一行。 由于有几千行,这个过程非常缓慢。

有没有办法一次完成整个数据表可能会更快?

DataTable的列数less于SQL表的数量。 其余的应该留空。

我发现SqlBulkCopy是一个简单的方法来做到这一点,并不需要在SQL Server中编写存储过程。

这里是我如何实现它的一个例子:

// take note of SqlBulkCopyOptions.KeepIdentity , you may or may not want to use this for your situation. using (var bulkCopy = new SqlBulkCopy(_connection.ConnectionString, SqlBulkCopyOptions.KeepIdentity)) { // my DataTable column names match my SQL Column names, so I simply made this loop. However if your column names don't match, just pass in which datatable name matches the SQL column name in Column Mappings foreach (DataColumn col in table.Columns) { bulkCopy.ColumnMappings.Add(col.ColumnName, col.ColumnName); } bulkCopy.BulkCopyTimeout = 600; bulkCopy.DestinationTableName = destinationTableName; bulkCopy.WriteToServer(table); } 

既然你已经有一个DataTable了,而且我假设你正在使用SQL Server 2008或更好,这可能是最直接的方法。 首先,在您的数据库中,创build以下两个对象:

 CREATE TYPE dbo.MyDataTable -- you can be more speciifc here AS TABLE ( col1 INT, col2 DATETIME -- etc etc. The columns you have in your data table. ); GO CREATE PROCEDURE dbo.InsertMyDataTable @dt AS dbo.MyDataTable READONLY AS BEGIN SET NOCOUNT ON; INSERT dbo.RealTable(column list) SELECT column list FROM @dt; END GO 

现在在你的C#代码中:

 DataTable tvp = new DataTable(); // define / populate DataTable using (connectionObject) { SqlCommand cmd = new SqlCommand("dbo.InsertMyDataTable", connectionObject); cmd.CommandType = CommandType.StoredProcedure; SqlParameter tvparam = cmd.Parameters.AddWithValue("@dt", tvp); tvparam.SqlDbType = SqlDbType.Structured; cmd.ExecuteNonQuery(); } 

如果您在问题中提供了更具体的细节,我会给出更具体的答案。

考虑这种方法 ,你不需要一个for循环:

 using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection)) { bulkCopy.DestinationTableName = "dbo.BulkCopyDemoMatchingColumns"; try { // Write from the source to the destination. bulkCopy.WriteToServer(ExitingSqlTableName); } catch (Exception ex) { Console.WriteLine(ex.Message); } } 

如果可以偏离DataTable – > SQL表的直线path,也可以通过一系列对象来完成:

1)DataTable – >通用的对象列表

 public static DataTable ConvertTo<T>(IList<T> list) { DataTable table = CreateTable<T>(); Type entityType = typeof(T); PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(entityType); foreach (T item in list) { DataRow row = table.NewRow(); foreach (PropertyDescriptor prop in properties) { row[prop.Name] = prop.GetValue(item); } table.Rows.Add(row); } return table; } 

来源和更多的细节可以在这里find。 缺less的属性将保持其默认值(0表示int s,null表示引用types)

2)将对象推入数据库

一种方法是使用EntityFramework.BulkInsert扩展。 但是,EF数据上下文是必需的。

它生成快速插入所需的BULK INSERT命令(用户定义的表types解决scheme比这慢得多)。

虽然不是直接的方法,但它有助于构build一个处理对象列表的基础,而不是DataTable ,这似乎更有效率 。

你可以用表值参数来做到这一点。

看看下面的文章:

http://www.codeproject.com/Articles/39161/C-and-Table-Value-Parameters

我更喜欢用户定义的数据types:它是超快的。

步骤1:在Sql Server DB中创build用户定义表

 CREATE TYPE [dbo].[udtProduct] AS TABLE( [ProductID] [int] NULL, [ProductName] [varchar](50) NULL, [ProductCode] [varchar](10) NULL ) GO 

步骤2:使用用户定义的types创build存储过程

 CREATE PROCEDURE ProductBulkInsertion @product udtProduct readonly AS BEGIN INSERT INTO Product (ProductID,ProductName,ProductCode) SELECT ProductID,ProductName,ProductCode FROM @product END 

第3步:从c#执行存储过程

 SqlCommand sqlcmd = new SqlCommand("ProductBulkInsertion", sqlcon); sqlcmd.CommandType = CommandType.StoredProcedure; sqlcmd.Parameters.AddWithValue("@product", productTable); sqlcmd.ExecuteNonQuery(); 

可能的问题:改变用户定义表

其实没有sql server命令来改变用户定义的types但是在pipe理工作室,你可以通过以下步骤来实现这一点

1.为该types生成脚本(在新的查询窗口中或作为文件)2.删除用户违规的表格。 3.修改创build脚本,然后执行。