SqlCommand.ExecuteNonQuery 抛出集合已修改;枚举操作可能不会执行

SqlCommand.ExecuteNonQuery throws Collection was modified; enumeration operation might not execute

我有一个简单的方法来执行 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 服务器。 任何帮助将不胜感激。

显示的代码 本身 应该没问题;这里的症状表明另一个线程正在同时接触同一个 Connection 实例,所以:不要那样做。连接不是线程安全的。这里的关键赠品以粗体显示:

This works fine without any issue [presumably meaning by itself] but when there is load or 20 thread simultaneously calling this method than sometime I get "Collection was modified; enumeration operation might no execute".

仅有时且仅在并发负载下发生的事情:通常是并发。建议:确定连接范围 - 每个线程,甚至每个方法,即

using (var conn = CreateOpenConnection())
using (var cmd = new SqlCommand(SQLQuery, conn))
{
    // ...
}