c# - SqlCommand.ExecuteNonQuery 抛出 Collection 被修改;枚举操作可能无法执行
问题描述
我有一个简单的方法来执行 SQL NON-QUERY 语句。这可以正常工作,没有任何问题,但是当有负载或 20 个线程同时调用此方法时,有时我会得到“集合已修改;枚举操作可能无法执行”。令人惊讶的是,我在此方法中没有任何枚举操作。
方法:
OpenConnection();
using (SqlCommand cmd = new SqlCommand(SQLQuery, Connection))
{
cmd.CommandType = CommandType.Text;
if (QueryParam.Count() > 0)
cmd.Parameters.AddRange(QueryParam.ToArray());
SqlParameter scopeParam = cmd.Parameters.AddWithValue("@ID", 0);
scopeParam.Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
uKey = (int)cmd.Parameters["@ID"].Value;
cmd.Parameters.Clear();
}
CloseConnection()
return uKey;
例外:
Exception Found: Collection was modified; enumeration operation might not execute.
Full Exception: System.InvalidOperationException: Collection was modified; enumeration operation might not execute.
at System.Data.SqlClient.TdsParser.TdsExecuteRPC(SqlCommand cmd, _SqlRPC[] rpcArray, Int32 timeout, Boolean inSchema, SqlNotificationRequest notificationRequest, TdsParserStateObject stateObj, Boolean isCommandProc, Boolean sync, TaskCompletionSource`1 completion, Int32 startRpc, Int32 startParam)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, Boolean inRetry, SqlDataReader ds, Boolean describeParameterEncryptionRequest)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
顺便提一下,我使用的是 .Net 4.0 和 SQL Server。任何帮助将不胜感激。
解决方案
本身显示的代码应该没问题;这里的症状表明另一个线程同时接触同一个Connection
实例,所以:不要那样做。连接不是线程安全的。这里的关键赠品以粗体显示:
这可以正常工作,没有任何问题[可能本身意味着],但是当有负载或 20 个线程同时调用此方法时,有时我会得到“集合已修改;枚举操作可能无法执行”。
仅在有时且仅在并发负载下才会发生的事情:通常是并发性。建议:范围连接 - 每个线程,甚至每个方法,即
using (var conn = CreateOpenConnection())
using (var cmd = new SqlCommand(SQLQuery, conn))
{
// ...
}
推荐阅读
- gradle - 无法为 API gradle 项目创建 HTTP 临时文件
- python - Blender > 使用 Python 将节点添加到灯光
- python - 嵌套的json api响应python数据框
- r - 始终在被 checkboxInput() 禁用时从 selectInput() 中选择特定项目
- flutter - DataTable 中的 Dismissible 或 Swipe Action DataRow
- flutter - 当用户在 Flutter 中选择日期时如何获取日期列表
- python - python 如何让多个命令同时运行?
- mongodb - Spring data mongo:当路径包含HashMap的键时,投影不起作用
- javascript - 我应该绕过皮诺儿童伐木工吗?
- javascript - 用于 npm 模式的 WebStorm 自动完成