gpt4 book ai didi

c# - 如何正确进行异步/并行数据库调用

转载 作者:行者123 更新时间:2023-12-02 02:26:17 25 4
gpt4 key购买 nike

我正在寻找处理多个数据库调用的正确方法,这些调用可能会从同时运行中受益。这些查询仅针对存储过程,这些存储过程使用以编程方式组装到我的 ASP.NET MVC 应用程序中的 DataTable 中的数据进行插入或合并。

当然,我看过一些关于asyncawait的信息,这似乎是我需要做的,但我没有清楚的理解如何实现它。一些信息表明,调用仍然是连续的,并且一个调用仍然会等待另一个调用完成。这似乎毫无意义。

最终,我想要一个解决方案,使我能够在完成最长过程所需的时间内运行所有查询。我希望所有查询也返回受影响的记录数(就像现在一样)。

这是我现在正在做的事情(绝不是平行的):

// Variable for number of records affected
var recordedStatistics = new Dictionary<string, int>();

// Connect to the database and run the update procedure
using (var dbc = new SqlConnection(db.Database.Connection.ConnectionString))
{
dbc.Open();

// Merge One procedure
using (SqlCommand cmd = new SqlCommand("MergeOneProcedure", dbc))
{
// 5 minute timeout on the query
cmd.CommandTimeout = 300;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@TVP", MergeOneDataTable);

// Execute procedure and record the number of affected rows
recordedStatistics.Add("mergeOne", cmd.ExecuteNonQuery());
}

// Merge Two procedure
using (SqlCommand cmd = new SqlCommand("MergeTwoProcedure", dbc))
{
// 5 minute timeout on the query
cmd.CommandTimeout = 300;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@TVP", MergeTwoDataTable);

// Execute procedure and record the number of affected rows
recordedStatistics.Add("mergeTwo", cmd.ExecuteNonQuery());
}

// Merge Three procedure
using (SqlCommand cmd = new SqlCommand("MergeThreeProcedure", dbc))
{
// 5 minute timeout on the query
cmd.CommandTimeout = 300;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@TVP", MergeThreeDataTable);

// Execute procedure and record the number of affected rows
recordedStatistics.Add("mergeThree", cmd.ExecuteNonQuery());
}

// Merge Four procedure
using (SqlCommand cmd = new SqlCommand("MergeFourProcedure", dbc))
{
// 5 minute timeout on the query
cmd.CommandTimeout = 300;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@TVP", MergeFourDataTable);

// Execute procedure and record the number of affected rows
recordedStatistics.Add("mergeFour", cmd.ExecuteNonQuery());
}

// Merge Five procedure
using (SqlCommand cmd = new SqlCommand("MergeFiveProcedure", dbc))
{
// 5 minute timeout on the query
cmd.CommandTimeout = 300;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@TVP", MergeFiveDataTable);

// Execute procedure and record the number of affected rows
recordedStatistics.Add("mergeFive", cmd.ExecuteNonQuery());
}

dbc.Close();
}

return recordedStatistics;

所有代码都在为 DataTable 组装数据的同一方法中。我对异步的有限理解使我相信我需要将以前的代码提取到它自己的方法中。然后我会调用该方法并等待返回。然而,我对此还不够了解。

我以前从未做过任何异步/并行/多线程编码。这种情况让我觉得现在是介入的最佳时机。也就是说,我想学习最好的方法,而不是必须忘记错误的方法。

最佳答案

以下是如何执行此操作的示例:

这里我创建了两个方法来包装两个操作,您需要对其他操作执行相同的操作:

public async Task<int> MergeOneDataTableAsync()
{
// Merge One procedure
using (SqlCommand cmd = new SqlCommand("MergeOneProcedure", dbc))
{
// 5 minute timeout on the query
cmd.CommandTimeout = 300;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@TVP", MergeOneDataTable);

return await cmd.ExecuteNonQueryAsync().ConfigureAwait(false);
}
}


public async Task<int> MergeTwoDataTableAsync()
{
// Merge Two procedure
using (SqlCommand cmd = new SqlCommand("MergeTwoProcedure", dbc))
{
// 5 minute timeout on the query
cmd.CommandTimeout = 300;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@TVP", MergeTwoDataTable);

return await cmd.ExecuteNonQueryAsync().ConfigureAwait(false);
}
}

请注意,我正在使用 ExecuteNonQueryAsync 方法来执行查询。

然后你原来的方法将如下所示:

using (var dbc = new SqlConnection(db.Database.Connection.ConnectionString))
{
dbc.Open();

Task<int> task1 = MergeOneDataTableAsync();
Task<int> task2 = MergeTwoDataTableAsync();

Task.WaitAll(new Task[]{task1,task2}); //synchronously wait

recordedStatistics.Add("mergeOne", task1.Result);
recordedStatistics.Add("mergeTwo", task2.Result);
}

请注意,我保持此方法同步。另一种选择(实际上是更好的选择)是将方法转换为异步方法,如下所示:

public async Task<Dictionary<string, int>> MyOriginalMethod()
{
//...
using (var dbc = new SqlConnection(db.Database.Connection.ConnectionString))
{
dbc.Open();

Task<int> task1 = MergeOneDataTableAsync();
Task<int> task2 = MergeTwoDataTableAsync();

int[] results = await Task.WhenAll(new Task<int>[]{task1,task2});

recordedStatistics.Add("mergeOne", results[0]);
recordedStatistics.Add("mergeTwo", results[1]);
}

//...
return recordedStatistics;
}

但这意味着您必须异步调用它( async all the way )。

关于c# - 如何正确进行异步/并行数据库调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35374697/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com