C# ADO.Net SqlCommand.EndExecuteReader上的SQLException
我试图通过ADO.NetC# ADO.Net SqlCommand.EndExecuteReader上的SQLException,c#,sql-server,asynchronous,ado.net,C#,Sql Server,Asynchronous,Ado.net,我试图通过ADO.NetSqlCommand在一个连接上异步调用存储过程 计时器每半秒触发一次调用,在一段时间内,我会按预期接收返回的结果,有时会收到以下错误: System.Data.SqlClient.SqlException(0x80131904):服务器上发生严重错误 当前命令。如果有结果,则应丢弃。 位于System.Data.SqlClient.SqlConnection.OnError(SqlException异常,Boolea n断开连接) 位于System.Data.SqlCl
SqlCommand
在一个连接上异步调用存储过程
计时器每半秒触发一次调用,在一段时间内,我会按预期接收返回的结果,有时会收到以下错误:
System.Data.SqlClient.SqlException(0x80131904):服务器上发生严重错误
当前命令。如果有结果,则应丢弃。位于System.Data.SqlClient.SqlConnection.OnError(SqlException异常,Boolea n断开连接)
位于System.Data.SqlClient.SqlInternalConnection.OnError(SqlException异常 ,布尔断开连接)
在System.Data.SqlClient.TdsParser.throweexception和warning()上 在System.Data.SqlClient.TdsParser.Run(RunBehavior,SqlCommand-cm dHandler、SqlDataReader数据流、BulkCopySimpleResultSet bulkCopyHandler、Tds ParserStateObject stateObj)
位于System.Data.SqlClient.SqlDataReader.ConsumerMetadata()
在System.Data.SqlClient.SqlDataReader.get_MetaData()
在System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds,运行 行为运行行为,字符串重置选项字符串)
位于System.Data.SqlClient.SqlCommand.CompleteAyncexecuteReader()
位于System.Data.SqlClient.SqlCommand.InternalEndExecuteReader(IAsyncResult asy ncResult,String endMethod)
位于System.Data.SqlClient.SqlCommand.EndExecuteReader(IAsyncResult asyncResult ) SQL日志反复显示以下错误: 服务器将断开连接,因为客户端驱动程序在会话处于单用户模式时发送了多个请求。当会话中仍在运行批处理时,客户端发送重置连接的请求,或者当会话重置连接时,客户端发送请求时,会发生此错误。请联系客户驱动程序供应商 我的连接字符串已设置MARS和Async=true。我目前正在使用SQLServer2008Express,尽管目标客户机将是一个成熟的SQLServer实例 我创建了以下控制台应用程序,它在我的机器上表现出相同的行为,我创建的
DummySp
只要调用它就返回
public class BusinessObject
{
public string Name {get; set;}
public void UpdateData(DataTable dataTable)
{
Console.WriteLine("{0}: new data received.",Name);
}
}
public class Program
{
private const string SpName = "DummySp";
private const string ConnectionsString = @"Data Source=(local)\sqlexpress;Initial Catalog=Test;Integrated Security=SSPI;Connection Timeout=3600";
private static readonly object DbRequestLock = new object();
private static readonly ManualResetEvent DatabaseRequestsComplete = new ManualResetEvent(false);
private static int _databaseRequestsLeft;
private static Timer _timer;
static readonly List<BusinessObject> BusinessObjects = new List<BusinessObject>
{
new BusinessObject{Name = "A"},
new BusinessObject{Name = "B"},
new BusinessObject{Name = "C"},
};
static void Main(string[] args)
{
_timer = new Timer(DoQuery, null, 0, 500);
Console.ReadLine();
_timer.Dispose();
}
private static void DoQuery(object state)
{
try
{
lock (DbRequestLock)
{
DatabaseRequestsComplete.Reset();
_databaseRequestsLeft = BusinessObjects.Count;
var builder = new SqlConnectionStringBuilder(ConnectionsString)
{
AsynchronousProcessing = true,
MultipleActiveResultSets = true
};
using (var connection = new SqlConnection(builder.ConnectionString))
{
connection.Open();
foreach (var businessObject in BusinessObjects)
{
var command = new SqlCommand(SpName, connection) { CommandType = CommandType.StoredProcedure };
command.BeginExecuteReader(Callback, new Tuple<SqlCommand, BusinessObject>(command, businessObject));
}
// need to wait for all to complete before closing the connection
DatabaseRequestsComplete.WaitOne(10000);
connection.Close();
}
}
}
catch (Exception ex)
{
Console.WriteLine("Following error occurred while attempting to update objects: " + ex);
}
}
private static void Callback(IAsyncResult result)
{
try
{
var tuple = (Tuple<SqlCommand, BusinessObject>)result.AsyncState;
var businessObject = tuple.Item2;
using (SqlCommand command = tuple.Item1)
{
using (SqlDataReader reader = command.EndExecuteReader(result))
{
using (var table = new DataTable(businessObject.Name))
{
table.Load(reader);
businessObject.UpdateData(table);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
finally
{
// decrement the number of database requests remaining and, if there are 0 fire the mre
if (Interlocked.Decrement(ref _databaseRequestsLeft) == 0)
{
DatabaseRequestsComplete.Set();
}
}
}
}
公共类BusinessObject
{
公共字符串名称{get;set;}
公共void UpdateData(数据表)
{
WriteLine(“{0}:接收到新数据。”,名称);
}
}
公共课程
{
private const string SpName=“DummySp”;
私有常量字符串connectionString=@“数据源=(本地)\sqlexpress;初始目录=测试;集成安全性=SSPI;连接超时=3600”;
私有静态只读对象DbRequestLock=new object();
私有静态只读ManualResetEvent数据库请求完成=新的ManualResetEvent(false);
私有静态int_数据库RequestsLeft;
专用静态定时器_定时器;
静态只读列表BusinessObjects=新列表
{
新业务对象{Name=“A”},
新业务对象{Name=“B”},
新业务对象{Name=“C”},
};
静态void Main(字符串[]参数)
{
_定时器=新定时器(DoQuery,null,0500);
Console.ReadLine();
_timer.Dispose();
}
私有静态void DoQuery(对象状态)
{
尝试
{
锁(DbRequestLock)
{
DatabaseRequestsComplete.Reset();
_databaseRequestsLeft=BusinessObjects.Count;
var builder=new-SqlConnectionStringBuilder(connectionstring)
{
AsynchronousProcessing=true,
MultipleActiveResultSets=true
};
使用(var connection=newsqlconnection(builder.ConnectionString))
{
connection.Open();
foreach(BusinessObjects中的var businessObject)
{
var command=newsqlcommand(SpName,connection){CommandType=CommandType.StoredProcedure};
BeginExecuteReader(回调,新元组(command,businessObject));
}
//在关闭连接之前,需要等待所有操作完成
DatabaseRequestsComplete.WaitOne(10000);
connection.Close();
}
}
}
捕获(例外情况除外)
{
WriteLine(“尝试更新对象时发生以下错误:“+ex”);
}
}
专用静态无效回调(IAsyncResult结果)
{
尝试
{
var tuple=(tuple)result.AsyncState;
var businessObject=tuple.Item2;
使用(SqlCommand=tuple.Item1)
{
使用(SqlDataReader=command.EndExecuteReader(结果))
{
使用(var table=newdatatable(businessObject.Name))
{
表1.负载(读卡器);
businessObject.UpdateData(表);
}
}
}
}
捕获(例外情况除外)
{
控制台写入线(ex);
}
最后
{
//减少剩余的数据库请求数,如果有0,则触发mre
if(互锁减量(ref _databaseRequestsLeft)==0)
{
DatabaseRequestsComplete.Set();
}
}
}
}
关于如何克服这个问题有什么想法吗
谢谢这不是直接回答我的问题,因此我没有将其标记为这样,但我认为值得展示每个对象具有单个连接的替代方案,因为这似乎可以避免此问题
private static void DoQuery(object state)
{
try
{
lock (DbRequestLock)
{
var builder = new SqlConnectionStringBuilder(ConnectionsString)
{
AsynchronousProcessing = true,
};
DatabaseRequestsComplete.Reset();
_databaseRequestsLeft = BusinessObjects.Count;
foreach (var businessObject in BusinessObjects)
{
var newConnection = new SqlConnection(builder.ConnectionString);
newConnection.Open();
var command = new SqlCommand(SpName, newConnection) { CommandType = CommandType.StoredProcedure };
command.BeginExecuteReader(Callback, new Tuple<SqlCommand, BusinessObject>(command, businessObject),CommandBehavior.CloseConnection);
}
// need to wait for all to complete DatabaseRequestsComplete.WaitOne(10000);
}
}
catch (Exception ex)
{
Console.WriteLine("Following error occurred while attempting to update objects: " + ex);
}
}
private static void Callback(IAsyncResult result)
{
var tuple = (Tuple<SqlCommand, BusinessObject>)result.AsyncState;
var businessObject = tuple.Item2;
SqlCommand command = tuple.Item1;
try
{
using (SqlDataReader reader = command.EndExecuteReader(result))
{
using (var table = new DataTable(businessObject.Name))
{
table.Load(reader);
businessObject.UpdateData(table);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
finally
{
// decrement the number of database requests remaining and, if there are 0 fire the mre
if (Interlocked.Decrement(ref _databaseRequestsLeft) == 0)
{
DatabaseRequestsComplete.Set();
}
try
{
command.Dispose();
command.Connection.Dispose();
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
}
私有静态void DoQuery(对象状态)
{
尝试