提问人:Ray 提问时间:7/2/2009 更新时间:1/27/2021 访问量:11968
SqlCommand.ExecuteReader() 何时返回 null?
When would SqlCommand.ExecuteReader() return null?
问:
使用调用该方法时,ReSharper告诉我,当我之后使用SqlDataReader对象时,我可能有一个NullReference异常。SqlCommand.ExecuteReader()
因此,使用以下代码:
using (SqlConnection connection = GetConnection())
{
using (SqlCommand cmd = connection.CreateCommand())
{
cmd.CommandText = ; //snip
using (SqlDataReader reader = cmd.ExecuteReader())
{
while (reader.Read())
{
//snip
}
}
}
}
该行带有下划线。while (reader.Read())
我的问题是,读取器对象什么时候会为空?我从未遇到过它,文档也没有提到它可能。我应该检查它是否为 null 还是可以安全忽略?
为什么 ReSharper 会认为它可能是 null,例如,它允许我使用 SqlCommand 而不建议检查它是否为 null?我猜 ExecuteReader 方法上有一个属性。
答:
我在其他几个领域也遇到了这个问题。他们似乎已经对 CLR 各个部分中的代码路径进行了分析。当他们发现返回 null 是可以想象的时,他们就会抱怨它。
在我抱怨的特定情况下,null 实际上不会发生。但是,他们将调用图跟踪到在某些情况下可以返回 null 的方法,并且 null 值可以传播到顶部。
因此,我称它为 ReSharper 错误(我以为我以前称它为 CLR 错误)。
这是一个误报。
反思 SqlDataReader.ExecuteReader,我可以看到读取器返回为 null 的唯一方式是,如果为 returnStream 传递了内部 RunExecuteReader 方法“false”,但事实并非如此。
在 SqlDataReader 的深处,读取器构造函数总是在某个时候被调用,所以我非常确定 ExecuteReader 在物理上不可能返回 null。
我已经确定了 ExecuteReader() 可以返回 null 的一个原因。
在我得到 null 的情况下,我向客户端发送了一个脚本来更新存储过程。设置了客户端的 Sql Server (2000),以便数据库用户需要执行存储过程的权限。当他们更新 SP 时,权限被删除,而不是重新分配。在此实例中,SqlCommand.ExecuteReader() 返回 null。
重新分配权限解决了此问题。
Resharper 是正确的,它可以返回 null 电位。
如果 的特定实现不允许冒泡 null 值,这并不重要 - 事实仍然是 IDataReader 是一个可以包含(或指向)null 的对象。ExecuteReader()
- 如果将来您决定使用不同的实现怎么办?
IDbCommand
- 如果该 IDbCommnd 实现的下一次更新将在代码中包含不同的流,这将允许冒泡 null,该怎么办?
你不需要知道接口的实现内部发生了什么,就可以正确使用它 - 你只需要知道接口,现在接口允许 null 作为返回值。
对我来说,它不是空的,但在 Powershell 中查看时不会输出任何内容。 当查询未返回任何行时,将发生这种情况。
评论