SQLクエリを実行するときに、このようなコードをいたるところに書いた請負業者がいます。
sql.Append(string.Format("SELECT TableId FROM ps_SavedTables WHERE guid = '{0}'", guid));
using (IDataReader reader = SqlHelper.GetDataReader(sql.ToString())) {
if (reader.Read()) {
result = reader.IsDBNull(0) ? string.Empty : reader[0].ToString();
}
//CDW added to close SqlDataReader
reader.Close();
}
GetDataReader クラスは App_Code ヘルパー ファイルにあり、次のように宣言されています。
public static SqlDataReader GetDataReader(string sql) {
return GetDataReader(sql, DefaultConnectionString);
}
public static SqlDataReader GetDataReader(string sql, int connectionTime) {
return GetDataReader(sql, DefaultConnectionString, connectionTime);
}
/// <summary>
/// Executes DB command ExecutedReader and returns the DataReader
/// </summary>
/// <param name="sql">SQL statement(s) to be used with DB command</param>
/// <param name="connectionString">Database connection string</param>
/// <returns>DataReader containing results of supplied SQL statement(s)</returns>
public static SqlDataReader GetDataReader(string sql, string connectionString) {
lock (_lock) {
SqlConnection connection = null;
try {
connection = GetConnection(connectionString);
//connection.Open();
using (SqlCommand cmd = new SqlCommand(sql, connection)) {
WriteDebugInfo("GetDataReader", sql);
return cmd.ExecuteReader(CommandBehavior.CloseConnection);
}
}
catch (Exception e) {
if (connection != null)
connection.Dispose();
throw new DataException(sql, connectionString, e);
}
}
}
次に、コードをローカルで実行し (統計のために大量の SQL を実行します)、2 つの異なるブラウザーで同じタイプのものを実行します。1 つのブラウザーは常にここでクラッシュします。
Server.ScriptTimeout = 300;
string returnCode = string.Empty;
using (SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["MainDll"].ToString())) {
connection.Open();
using (SqlCommand command = new SqlCommand(sql.ToString(), connection)) {
command.CommandType = CommandType.Text;
command.CommandTimeout = 300;
returnCode = (string)command.ExecuteScalar();
Dispose();
}
Dispose();
}
スタック トレースは次のとおりです。
.NET Framework execution was aborted by escalation policy because of out of memory.
System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
System.InvalidOperationException:
at System.Data.SqlClient.SqlInternalConnectionSmi.ValidateConnectionForExecute(SqlCommand command)
at System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command)
at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader()
at PowerStatRegression.share.JbLog.SendResultSet(String str, SqlConnection conn)
at StoredProcedures.SavePowerStatErrors(ApplicationContext app, SqlString strUID, Int32 seqId, List`1 errors, Int32 errorType)
at StoredProcedures.CreatePowerStatCorr(SqlString strUID, Int32 seqId, Int32 flagProgress)
at StoredProcedures.SpCreatePowerStatCorr(SqlString strUID, Int32 seqId, Int32 flagProgress)
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Data.SqlClient.SqlException: .NET Framework execution was aborted by escalation policy because of out of memory.
System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
System.InvalidOperationException:
at System.Data.SqlClient.SqlInternalConnectionSmi.ValidateConnectionForExecute(SqlCommand command)
at System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command)
at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader()
at PowerStatRegression.share.JbLog.SendResultSet(String str, SqlConnection conn)
at StoredProcedures.SavePowerStatErrors(ApplicationContext app, SqlString strUID, Int32 seqId, List`1 errors, Int32 errorType)
at StoredProcedures.CreatePowerStatCorr(SqlString strUID, Int32 seqId, Int32 flagProgress)
at StoredProcedures.SpCreatePowerStatCorr(SqlString strUID, Int32 seqId, Int32 flagProgress)
Source Error:
Line 705: command.CommandType = CommandType.Text;
Line 706: command.CommandTimeout = 300;
Line 707: returnCode = (string)command.ExecuteScalar();
Line 708: //Dispose();
Line 709: }
Source File: c:\PowerStats\datalab\powerstats\output.aspx.cs Line: 707
Stack Trace:
[SqlException (0x80131904): .NET Framework execution was aborted by escalation policy because of out of memory.
System.InvalidOperationException: There is already an open DataReader associated with this Command which must be closed first.
System.InvalidOperationException:
at System.Data.SqlClient.SqlInternalConnectionSmi.ValidateConnectionForExecute(SqlCommand command)
at System.Data.SqlClient.SqlConnection.ValidateConnectionForExecute(String method, SqlCommand command)
at System.Data.SqlClient.SqlCommand.ValidateCommand(String method, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader()
at PowerStatRegression.share.JbLog.SendResultSet(String str, SqlConnection conn)
at StoredProcedures.SavePowerStatErrors(ApplicationContext app, SqlString strUID, Int32 seqId, List`1 errors, Int32 errorType)
at StoredProcedures.CreatePowerStatCorr(SqlString strUID, Int32 seqId, Int32 flagProgress)
at StoredProcedures.SpCreatePowerStatCorr(SqlString strUID, Int32 seqId, Int32 flagProgress)
]
System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) +1950522
System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection) +4856715
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) +194
System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +1121
System.Data.SqlClient.SqlDataReader.ConsumeMetaData() +33
System.Data.SqlClient.SqlDataReader.get_MetaData() +83
System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +293
System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async) +954
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result) +162
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method) +32
System.Data.SqlClient.SqlCommand.ExecuteScalar() +139
Output.RunTable(String outputType, String _outputDataType) in c:\PowerStats\datalab\powerstats\output.aspx.cs:707
Output.ProcessPage() in c:\PowerStats\datalab\powerstats\output.aspx.cs:652
Output.Page_Load(Object sender, EventArgs e) in c:\PowerStats\datalab\powerstats\output.aspx.cs:644
System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
System.Web.UI.Control.OnLoad(EventArgs e) +99
System.Web.UI.Control.LoadRecursive() +50
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +627
--------------------------------------------------------------------------------
Version Information: Microsoft .NET Framework Version:2.0.50727.5456; ASP.NET Version:2.0.50727.5456
SqlDataReader の割り当てが正しく解除されないのはなぜですか?