我在一个错误日志中发现了这个,并试图找出它是如何可能的。 NullReferenceException不是每天都会在.net基类中变得很深!SqlDataReader抛出NullReferenceException!什么可能导致这种情况,我该如何调试?
1) Exception Information
*********************************************
Exception Type: System.NullReferenceException
Message: Object reference not set to an instance of an object.
Data: System.Collections.ListDictionaryInternal
TargetSite: Void Bind(System.Data.SqlClient.TdsParserStateObject)
HelpLink: NULL
Source: System.Data
StackTrace Information
*********************************************
at System.Data.SqlClient.SqlDataReader.Bind(TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult esult)
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.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet)
at MyCode.Shared.Data.DataSocket.GetTable(String SPString)
at <rest of stack trace>
我唯一能想出是有一个(苗条)的机会有两个线程在同一时间执行相同的方法,并且一个清除或修改被传递到填充DataSet() 。所以我的问题是真的:
- 这怎么可能例外抛出
- 莫非多线程的情况下导致此异常
- 我怎么能肯定,例如,是否有办法,我也可以通过系统步骤.Data方法来复制问题?
顺便说一句,我发现一对夫妇的这一问题的其他情况下,一个在this线程,另一个在某人的页面this谷歌缓存。这两者似乎都没有任何帮助。
正在执行矿的GetTable()方法是这样的:
public DataTable GetTable(string SPString)
{
//Setup the data objects by calling helper
prepareDataAdaptor(SPString,CommandType.Text);
dataAdaptor.Fill(dataSet);
dataAdaptor.SelectCommand.Connection.Close();
DataTable dt;
//ensure we dispose okay
using(dataSet)
{
if(dataSet.Tables.Count==0)
{
dataSet.Tables.Add(new DataTable("EmptyTable"));
}
dt=dataSet.Tables[0];
//because we are disposing we need to remove the table from the dataset
dataSet.Tables.Clear();
}
return dt;
}
private void prepareDataAdaptor(string SPString,CommandType Type)
{
checkForConnection();
dataSet=new DataSet();
dbCommand.CommandText=SPString;
dbCommand.CommandTimeout = MySettings.CommandTimeout;
dataAdaptor.SelectCommand=dbCommand;
dataAdaptor.SelectCommand.CommandType=Type;
dataAdaptor.SelectCommand.Connection=dbConnection;
dataAdaptor.SelectCommand.Parameters.Clear();
}
dataAdaptor(原文如此)是声明为填充有一个SqlDataAdapter一个IDbDataAdapter一个实例变量。数据集是DataSet类型的实例变量。
我的理论是,线程A贯穿并进入SqlDataAdapter.Fill()方法。同时线程B也执行,并做一些事情弄糟线程A,像这一行:
dataAdaptor.SelectCommand.Connection.Close();
我可以看到我的这个代码是不是线程安全的,但我怎么能肯定这是问题导致上述例外?
非常感谢您的任何建议!
罗里
编辑:糟糕拼写固定情况。没有在代码中更新它,因为它就是这样。
更新:我同意这个代码有几个问题应该修复,但我的主要兴趣是是否有任何方法来验证是否会导致此错误的线程问题。鉴于我的应用程序,它有点牵强,但我能想到的唯一一件事。在我修改代码以使其更好之前,我想确保找到异常的原因,以便我确定我已修复它。
有没有什么办法可以进入.NET代码呢?我使用的是VS 2005/.net 2.0,但我认为在VS 2008中可以查看.NET框架源代码?如果是这种情况,我可以创建一个2线程场景并逐步重新创建这个问题?或者有没有一种方法不需要我安装VS 2008?
“稍有牵强”是这样的代码多线程? 使数据集局部变量,看看它是否再次发生。 – dotjoe 2008-12-15 02:45:36