我有一些使用datareader访问存储过程的代码,它返回一些输出参数和结果集。使用使用块创建datareader。
问题是我有时得到一个"对象引用未设置为对象的实例"在尝试访问输出参数时。我知道,如果在尝试访问输出参数时未关闭datareader,则通常会收到此错误。但是,因为在using块中访问了datareader,并且访问输出参数的代码在using块之外,所以参数永远不应为null。
这怎么可能?
SqlCommand command = new SqlCommand();
command.CommandText = "stored proc";
CommandBehavior commandBehavior = new CommandBehavior();
using (var reader = command.ExecuteReader(commandBehavior))
{
while(reader.Read())
{
//access record values
}
}
var param1 = command.Parameters["firstParam"].Value; //<-- null reference error here
为简洁起见,我省略了一些代码。
代码和SQL服务器在VM上运行。
其他相关事实:C#.Net Framework 4.0,SQL Server 2012
答案 0 :(得分:0)
您的代码结构看起来正确,这使我考虑可能存在于您的省略代码或存储过程中的原因。如果你已经检查了这些,我很抱歉。
对于某些查询,SQL存储过程是否为参数值返回null?
在省略的代码中,是否有任何更改了commandBehavior - 如果行为设置为CloseConnection
,那么就有你的理由。
顺便说一句。在您的内容中创建和使用commandBahavior()
是不必要的 - 您拥有的是您的代码与reader = command.ExecuteReader()
完全相同
您是否在command.Parameters["firstParam"]
之前初始化command.ExecuteReader()
,因为它设置了direction = output和正确的类型。
您是否为某些存储过程运行返回多个记录集?我相信参数在这种情况下会受到干扰,尽管我从来没有亲身体验过这一点
答案 1 :(得分:0)
请尝试以下代码,我已经测试过它工作正常。
SqlConnection con = new SqlConnection("Data Source=local;Initial Catalog=AdventureWorks;Integrated Security=SSPI;");
SqlCommand command = new SqlCommand("Test",con);
if (con.State == ConnectionState.Closed)
{
con.Open();
}
command.Parameters.AddWithValue("@parm1", "Hi");
command.Parameters.Add("@parm2",SqlDbType.VarChar,500).Value = "";
command.Parameters["@parm2"].Direction = ParameterDirection.Output;
command.CommandType = CommandType.StoredProcedure;
//CommandBehavior commandBehavior = new CommandBehavior();
var parm2 = "";
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
//access record values
}
reader.Close();
parm2 = Convert.ToString(command.Parameters["@parm2"].Value);
}
SP:
CREATE PROCEDURE Test
@parm1 varchar(100),
@parm2 Varchar(200) = '' OUTPUT
AS
BEGIN
SELECT 1 AS parm1
SELECT @parm2 = 'Shakti Singh'
END
答案 2 :(得分:0)
可能你的代码是正确的,你只需要在你提到的行上处理null,请尝试用以下代码替换该行。
var param1 = Convert.ToString(command.Parameters["firstParam"].Value);
答案 3 :(得分:0)
使用&#39;作为&#39;字符串关键字
command.Parameters["@parm2"].Value as string
答案 4 :(得分:0)
我能够通过在数据库上运行SQL分析器来跟踪问题。我很幸运地发现了一个错误。检查SQL日志显示存在死锁。但是,应用程序未收到错误。为了模拟错误,请尝试以下存储过程(从@Shakti复制):
CREATE PROCEDURE Test
@parm1 varchar(100),
@parm2 Varchar(200) = '' OUTPUT
AS
BEGIN
SELECT 1 AS parm1
SELECT * FROM some_table
SELECT @parm2 = 'Shakti Singh'
THROW 1,'Deadlock Error!',1 --error number not important, any error here will simulate the problem, in my case a deadlock
END
在应用程序中,您将能够读取数据读取器而不会出现任何错误,但您将无法访问输出参数。但是,如果您在SELECT *之前抛出错误,应用程序将收到错误,但您显然无法通读数据读取器。