C#:在 Parallel.ForEach 中打开 SqlConnection 时出现连接错误
C#: Connection Errors opening SqlConnection inside Parallel.ForEach
我有一个 .NET Core C# 控制台应用程序,它执行大量计算,然后使用 Dapper(和 Dapper.Contrib)将结果写入 SQL Server 2016 Developer Edition 数据库。我遇到的问题是,当我 运行 并行处理很多项(例如,大于 1000)时,我开始在 .Open()
调用中出现间歇性连接失败,说
A network-related or instance-specific error occurred...
这通常发生在已经成功插入几千行之后。
代码的简化版本如下所示:
Parallel.ForEach(collection, (item) =>
{
var results = item.Calculate(parameters);
dal.Results.Insert(results);
allResults.AddRange(results);
});
在 Insert 方法内部,它看起来像这样:
public override void Insert(IEnumerable<Result> entities)
{
using (var connection = GetConnection())
{
connection.Open();
using (var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted))
{
connection.Insert(entities, transaction);
transaction.Commit();
}
}
}
关于代码的其他一些我认为不会影响此但可能相关的事情:
dal.Results
只是一个包含 Insert()
方法的存储库,并使用连接字符串进行预初始化,该连接字符串用于每次实例化 new SqlConnection(connectionString)
GetConnection()
被调用。
allResults
是一个 ConcurrentBag<Result>
,我用它来存储所有结果以供以后在 Parallel.ForEach
[=44 之外使用=]
我正在使用事务,因为它似乎以这种方式执行得更好,但如果这可能导致问题,我愿意接受建议。
在此先感谢您对此问题的任何指导!
并行执行大量 IO 绑定的数据库操作没有任何优势。
你应该创建发烧但更大的数据束以最小的数据库事务量插入。这可以通过多种方式实现:
- 使用 .NET framework 提供的 SQL Bulk Insert 操作
- 通过使用专用于高速批量操作的external library
- 通过制作sql 以数据数组为参数的存储过程。有关 table 值参数的更多信息,请参阅 https://docs.microsoft.com/en-us/sql/relational-databases/tables/use-table-valued-parameters-database-engine
所以请尝试以下操作:在并行循环中执行 CPU 密集型计算,并在循环后将所有结果保存到数据库中。
我有一个 .NET Core C# 控制台应用程序,它执行大量计算,然后使用 Dapper(和 Dapper.Contrib)将结果写入 SQL Server 2016 Developer Edition 数据库。我遇到的问题是,当我 运行 并行处理很多项(例如,大于 1000)时,我开始在 .Open()
调用中出现间歇性连接失败,说
A network-related or instance-specific error occurred...
这通常发生在已经成功插入几千行之后。
代码的简化版本如下所示:
Parallel.ForEach(collection, (item) =>
{
var results = item.Calculate(parameters);
dal.Results.Insert(results);
allResults.AddRange(results);
});
在 Insert 方法内部,它看起来像这样:
public override void Insert(IEnumerable<Result> entities)
{
using (var connection = GetConnection())
{
connection.Open();
using (var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted))
{
connection.Insert(entities, transaction);
transaction.Commit();
}
}
}
关于代码的其他一些我认为不会影响此但可能相关的事情:
dal.Results
只是一个包含Insert()
方法的存储库,并使用连接字符串进行预初始化,该连接字符串用于每次实例化new SqlConnection(connectionString)
GetConnection()
被调用。
[=44 之外使用=]allResults
是一个ConcurrentBag<Result>
,我用它来存储所有结果以供以后在Parallel.ForEach
我正在使用事务,因为它似乎以这种方式执行得更好,但如果这可能导致问题,我愿意接受建议。
在此先感谢您对此问题的任何指导!
并行执行大量 IO 绑定的数据库操作没有任何优势。
你应该创建发烧但更大的数据束以最小的数据库事务量插入。这可以通过多种方式实现:
- 使用 .NET framework 提供的 SQL Bulk Insert 操作
- 通过使用专用于高速批量操作的external library
- 通过制作sql 以数据数组为参数的存储过程。有关 table 值参数的更多信息,请参阅 https://docs.microsoft.com/en-us/sql/relational-databases/tables/use-table-valued-parameters-database-engine
所以请尝试以下操作:在并行循环中执行 CPU 密集型计算,并在循环后将所有结果保存到数据库中。