多线程处理时,铁路超高插入到标识列中
本文关键字:插入 标识 铁路 高插入 多线程处理 | 更新日期: 2023-09-27 18:22:14
我有一个数据迁移工具,直到最近它似乎还运行得很好。
我使用Parallel.Foreach运行了一组数据行,计算出一些要插入到表的新记录中的变量,然后运行SQL语句来插入数据。
Parallel.ForEach<DataRow>(dataTable.Rows, row =>
{
string reference = row["ref"].ToString();
int version = (int)row["version"];
string insertStatement = "INSERT INTO Item (Reference, Version) VALUES (@reference, @version)";
_database.ExecuteCommand(insertStatement, new SqlServerCeParameter[]
{
new SqlServerCeParameter("@reference", reference, SqlDbType.NVarChar),
new SqlServerCeParameter("@version", version, SqlDbType.Int),
});
});
public void ExecuteCommand(string sql, SqlServerCeParameter[] parameters)
{
//create the command that will execute the Sql
using (var command = new SqlCeCommand(sql, _connection))
{
//add any parameters
if (parameters != null) command.Parameters.AddRange(parameters.Select(p => p.ParameterBehind).ToArray());
try
{
//open the connection
if (_connection.State == ConnectionState.Closed) _connection.Open();
//execute the command
command.ExecuteNonQuery();
}
catch (SqlCeException ex)
{
//only catch if the native error is the duplicate value exception otherwise throw as normal
if (ex.NativeError != 25016) throw;
}
finally
{
//explicitly close command
command.Dispose();
}
}
}
然而,我得到了一个聚合异常,其内部异常如下:
{"The column cannot contain null values. [ Column name = ID,Table name = Item ]"}
表格结构如下:
CREATE TABLE Item
(
ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
Reference NVARCHAR(50) NOT NULL,
Version INT NOT NULL
);
现在我不理解这个错误,因为ID是一个标识列。
我的一个想法是,由于多线程,它不能同时计算两个id,但这似乎是一个非常脆弱的原因,因为SqlServerCe适用于多用户环境。
重要信息:SQL CE对象不是线程安全的。您在每个调用中使用_connection
,我猜这是SqlCeConnection
的单个实例?
建议每个线程应该使用自己单独的连接,而不是在多个线程之间共享。因此,尝试在ExecuteCommand
方法中创建一个新的SqlCeConnection
,并每次连接。
这可能无法实现您所希望/期望的速度提高,但我不确定多线程是否能如您所期望的那样工作。你需要多个核心/处理器才能有效,这本身就是一个深刻的主题。
确保表的IDENTITY_INSERT为ON。