Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/340.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 向SQL数据库插入记录的更快方法_C#_Sql_Sql Server_For Loop - Fatal编程技术网

C# 向SQL数据库插入记录的更快方法

C# 向SQL数据库插入记录的更快方法,c#,sql,sql-server,for-loop,C#,Sql,Sql Server,For Loop,我有一个每小时在数据库中插入/更新数千条记录的工具。它将输入读入数据表,并逐行运行SQL命令: for(int i = 0; i < dataTable.Rows.Count; i++) { string sqlConnectionString = "server, db, user, pass, etc."; SqlConnection sqlDBConnection = new SqlConnection(sqlConnectionString);

我有一个每小时在数据库中插入/更新数千条记录的工具。它将输入读入
数据表
,并逐行运行SQL命令:

for(int i = 0; i < dataTable.Rows.Count; i++)
{
    string sqlConnectionString = "server, db, user, pass, etc.";
    SqlConnection sqlDBConnection = new SqlConnection(sqlConnectionString);

    string query = @"INSERT INTO table 
                    (col1, col2, col3, etc.) 
                    VALUES 
                    (@col1, @col2, @col3, etc.)";
    SqlCommand queryCommand = new SqlCommand(query, sqlDBConnection);

    queryCommand.Parameters.Add("@col1", SqlDbType.Int);
    queryCommand.Parameters["@col1"].Value = Convert.ToInt32(dataTable.Rows[i][0]);

    queryCommand.Parameters.Add("@col2", SqlDbType.VarChar);
    queryCommand.Parameters["@col2"].Value = dataTable.Rows[i][1].ToString();

    queryCommand.Parameters.Add("@col3", SqlDbType.VarChar);
    queryCommand.Parameters["@col3"].Value = dataTable.Rows[i][2].ToString();

    sqlDBConnection.Open();
    queryCommand.ExecuteNonQuery();
    sqlDBConnection.Close();
}
for(int i=0;i

它工作得很好,但速度很慢。您有更快的解决方案吗?

将批量插入与或一起使用。

这应该会加快速度

这很慢,因为每个插入都是单独处理的,这会导致事务时间的开销。 尝试使用不同的方法进行批量插入。 无论是在框架上(比如SpringDataBulk),还是通过更改查询一次插入多个值

insert into table (col1, col2, col3, ...)
values            (val1, val2, cal3, ...),
                  (val1, val2, cal3, ...),
                  (val1, val2, cal3, ...), ...

但是不要强迫所有人都不监督数据库连接的缓冲区大小。

因为您的数据已经在数据表中,我认为最好的方法是使用。e、 g


为了更新现有记录,如果您使用SqlDataAdapter填充了DataTable,则可以使用该方法。如果不是,那么我建议在SQL中处理upsert。因为您使用的是SQL Server 2012,所以可以使用表值参数。第一步是创建您的

这应该与您的c#数据表具有相同的定义

然后,下一步是创建一个存储过程,该存储过程接受此类型作为参数,并根据是否存在匹配项,使用
MERGE
插入或更新记录:

CREATE PROCEDURE dbo.UpsertYourTable @Table dbo.YourTableType READONLY
AS
BEGIN
    MERGE dbo.YourTable WITH (HOLDLOCK) AS t
    USING @Table AS s
        ON s.Col1 = t.Col1 -- OR HOWEVER YOU IDENTIFY EXISTING RECORDS
    WHEN MATCHED THEN UPDATE
        SET Col2 = Col2,
            Col3 = Col4
    WHEN NOT MATCHED THEN 
        INSERT (Col1, Col2, Col3, Col4)
        VALUES (s.Col1, s.Col2, s.Col3, 'Test');

END;
GO
最后,要从c#调用此函数,您可以使用:

string sqlConnectionString = "server, db, user, pass, etc.";
using (var connection = new SqlConnection(sqlConnectionString))
using (var command = new SqlCommand("dbo.UpsertYourTable", connection))
{
    command.CommandType = CommandType.StoredProcedure;
    var tvp = new SqlParameter("@Table", SqlDbType.Structured);
    tvp.Value = dataTable;
    tvp.TypeName = "dbo.YourTableType";
    command.Parameters.Add(tvp);
    command.ExecuteNonQuery();
}

你有没有考虑过如何使用SSIS?或通过
批量插入
。无论您选择什么选项,您都希望最大限度地减少到db的连接数-一次数千次的呼叫将是密集的

不要为每个插件断开/连接。组一起插入到更大的事务中等+1在这方面,SQL批量复制是迄今为止最快的方法,如果您有架构并且可以自己增量生成ID,我个人每秒为批量复制完成20000多行。这里有一个可能有用的例子:这看起来不错。您是否知道如何加快更新现有记录的速度?也可以不使用例如col2列映射,但让我们假设将给定字符串写入col2中,如“test”?您不需要将此列添加到数据表中。您使用的是哪个版本的SQL Server?不建议使用Merge,因为它存在许多问题:默认情况下不会触发触发器,但您可以使用来启用它们,例如
new SqlBulkCopy(sqlConnectionString,SqlBulkCopyOptions.FireTriggers)
CREATE PROCEDURE dbo.UpsertYourTable @Table dbo.YourTableType READONLY
AS
BEGIN
    MERGE dbo.YourTable WITH (HOLDLOCK) AS t
    USING @Table AS s
        ON s.Col1 = t.Col1 -- OR HOWEVER YOU IDENTIFY EXISTING RECORDS
    WHEN MATCHED THEN UPDATE
        SET Col2 = Col2,
            Col3 = Col4
    WHEN NOT MATCHED THEN 
        INSERT (Col1, Col2, Col3, Col4)
        VALUES (s.Col1, s.Col2, s.Col3, 'Test');

END;
GO
string sqlConnectionString = "server, db, user, pass, etc.";
using (var connection = new SqlConnection(sqlConnectionString))
using (var command = new SqlCommand("dbo.UpsertYourTable", connection))
{
    command.CommandType = CommandType.StoredProcedure;
    var tvp = new SqlParameter("@Table", SqlDbType.Structured);
    tvp.Value = dataTable;
    tvp.TypeName = "dbo.YourTableType";
    command.Parameters.Add(tvp);
    command.ExecuteNonQuery();
}