C# 一次将整个数据表插入数据库,而不是逐行插入?

C# 一次将整个数据表插入数据库,而不是逐行插入?,c#,sql,sql-server,C#,Sql,Sql Server,我有一个DataTable,需要将整个内容推送到一个数据库表中 我可以用foreach一次插入每一行,把所有的东西都放进去。但是,由于有几千行,所以速度非常慢 是否有任何方法可以一次完成整个数据表,从而更快 DataTable的列数少于SQL表。其余部分应保留为空。您可以使用表值参数来执行此操作 请看以下文章: 因为您已经有了一个DataTable,而且我假设您使用的是SQL Server 2008或更好的版本,所以这可能是最简单的方法。首先,在数据库中创建以下两个对象: 创建类型dbo.MyD

我有一个DataTable,需要将整个内容推送到一个数据库表中

我可以用foreach一次插入每一行,把所有的东西都放进去。但是,由于有几千行,所以速度非常慢

是否有任何方法可以一次完成整个数据表,从而更快


DataTable的列数少于SQL表。其余部分应保留为空。

您可以使用表值参数来执行此操作

请看以下文章:


因为您已经有了一个DataTable,而且我假设您使用的是SQL Server 2008或更好的版本,所以这可能是最简单的方法。首先,在数据库中创建以下两个对象:

创建类型dbo.MyDataTable-您可以在这里更具体 作为桌子 col1 INT, col2日期时间 -等等。数据表中的列。 ; 去 创建过程dbo.InsertMyDataTable @dt作为dbo.MyDataTable只读 像 开始 不计数; 插入dbo.RealTablecolumn list从@dt中选择column list; 终止 去 现在在您的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();
}

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

我发现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);
}

我更喜欢用户定义的数据类型:它非常快

步骤1:在Sql Server数据库中创建用户定义的表

步骤2:创建用户定义类型的存储过程

步骤3:从c执行存储过程

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

实际上,没有sql server命令来更改用户定义的类型 但在ManagementStudio中,您可以通过以下步骤实现这一点

1.在新查询窗口中或作为文件生成类型的脚本 2.删除用户定义的表。
3.修改创建脚本,然后执行。

如果可以稍微偏离DataTable->SQL table的直线路径,也可以通过对象列表执行:

1数据表->对象的通用列表

来源和更多细节可以找到。缺少的属性将保留为int的默认值0,引用类型的默认值为null等

2将对象推入数据库

一种方法是使用EntityFramework.BulkInsert扩展。不过,需要EF datacontext

它生成快速插入用户定义的表类型解决方案所需的大容量插入命令要比这慢得多

虽然不是直截了当的方法,但它有助于构建使用对象列表而不是数据表的基础。

考虑到,您不需要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);
    }
}

SqlBulkCopy绝对是SqlBulkCopy示例的一种方式。如果我没有弄错的话,这将只适用于相对少量的数据,因为@dt将逐行填充。SqlBulkCopy对于成千上万的大数据和更多的数据来说,效率要高得多。@Aaron Bertrand我为3个不同的表插入了超过600000条记录。表A不依赖于任何其他表,而表B需要来自表A的主键,表C需要来自A和B的主键值。表D也需要10000条记录更新。如何实现这一点。在插入过程中,我可以从Datatable Headers检查并创建一个表吗?对于像我这样的新手:bulkCopy.WriteToServerExitingSqlTableName;这里ExistingSqlTableName表示现有的sql数据源。它可以是sql表、datatable或读取器。
CREATE PROCEDURE ProductBulkInsertion 
@product udtProduct readonly
AS
BEGIN
    INSERT INTO Product
    (ProductID,ProductName,ProductCode)
    SELECT ProductID,ProductName,ProductCode
    FROM @product
END
SqlCommand sqlcmd = new SqlCommand("ProductBulkInsertion", sqlcon);
sqlcmd.CommandType = CommandType.StoredProcedure;
sqlcmd.Parameters.AddWithValue("@product", productTable);
sqlcmd.ExecuteNonQuery();
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;
}
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);
    }
}