如果我使用相同的ConnectionString从多个线程执行查询,是否会有问题?如果两个或多个线程尝试同时发送数据会怎样?
string globalConnectionString = @"some_stringHere!";
//create new backgroundWorker if new logFile is created (txt file).
// ....
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
// get some data from created logFile
string serialNumber = getSerialNumber(logFile);
string testResult = getTestResult(logFile);
// if server is online, send data
if(serverIsOnline)
{
using(SqlConnection connection = new SqlConnecton(globalConnectionString))
{
SqlCommand someCommand = new SqlCommand("some insert/update command here!", connection);
connection.Open();
Command.ExecuteNonQuery();
connection.Close();
}
}
}
最佳答案
如果正确使用并发连接就可以了
假设正确的理由,并发使用多个连接没有问题。数据库可以处理数千个并发客户端连接。
并行执行相同的慢速查询以使其完成得更快,可能会使其变得更慢,因为每个连接都可能阻塞其他连接。许多数据库已经使查询处理并行化,与粗略的客户端并行性相比,产生的结果要好得多。
如果您想使慢速查询更快,则可以通过调查慢速原因并解决性能问题来获得更好的结果。例如,如果要插入1万行,则使用SqlBulkCopy或BULK INSERT
加载行要比执行10K INSERT快,而INSERT最终会相互阻塞以访问同一张表甚至数据页
您可以使用相同的连接来执行异步查询(例如,使用ExecuteNonQueryAsync()
,ExecuteReaderAsync()
等,前提是它们一个接一个地执行。)您不能在同一连接上执行多个并发查询,至少不能不经过一些麻烦而已。
真正的问题
真正的问题是首先使用BackgroundWorker。自2012年引入async/await
以来,该类已过时。使用BGW,很难组合多个异步操作。可以通过Progress<T>
类获得进度报告,并可以通过CancellationTokenSource
进行协作取消。检查Async in 4.5: Enabling Progress and Cancellation in Async APIs以获得详细说明。
您可以仅使用await command.ExecuteNonQueryAsync()
替换代码中的BGW调用。您可以创建一个异步方法来执行将数据插入数据库的操作:
private async Task InsertTestData(string serialNumber,string testResult)
{
// if server is online, send data
if(serverIsOnline)
{
using(SqlConnection connection = new SqlConnecton(globalConnectionString))
{
var someCommand = new SqlCommand("some insert/update command here!", connection);
someCommand.Parameters.Add("@serial",SqlDbType.NVarChar,30).Value=serialNumber;
...
connection.Open();
Command.ExecuteNonQueryAsync();
}
}
}
如果检索序列号和测试数据很耗时,则可以使用Task.Run
在后台运行它们: string serialNumber = await Task.Run(()=>getSerialNumber(logFile));
string testResult = await Task.Run(()=>getTestResult(logFile));
await InsertTestData(serialNumber,testResult);
您还可以使用像Dapper这样的库来简化数据库:private async Task InsertTestData(string serialNumber,string testResult)
{
// if server is online, send data
if(serverIsOnline)
{
using(SqlConnection connection = new SqlConnecton(globalConnectionString))
{
await connection.ExecuteAsync("INSERT .... VALUES(@serial,@test)",
new {serial=serialNumber,test=testResults});
}
}
}
Dapper将生成一个参数化查询,并按名称将查询中的参数与匿名对象中的属性进行匹配。
关于c# - 来自后台 worker 冲突的查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64328828/