reader.Read()将布尔值计算为true或false

时间:2014-02-12 23:23:01

标签: c# ado.net

假设我有以下c#代码:

private bool MethodName(string inviteId)
{
  var command = new SqlCommand
    {
      CommandText = "SELECT statement goes here",
      Connection = conn
    } ;
  var reader = command.ExecuteReader();
  return reader.Read();
}

让我们假设,如果存在符合查询条件的行,则虚构的SQL查询将返回行。如果我要运行此代码并且数据库中没有任何内容符合条件,那么该方法应该评估错误,正确吗?换句话说,如果查询返回一个空结果,它会评估为false,但如果它返回行,它将评估为true吗?

由于

3 个答案:

答案 0 :(得分:2)

您正在执行SqlDataReader.Read(),其返回值记录如下:

  

如果有更多行,则为true;否则是假的。

鉴于您的查询返回0行,它将立即返回false。您的 F5 键也可以告诉您这一点。 ; - )

答案 1 :(得分:2)

是的,你是对的。你也可以使用HasRows属性而不是Read方法。

return reader.HasRows;

答案 2 :(得分:1)

你的方法

private bool MethodName(string inviteId)
{
  var command = new SqlCommand
  {
    CommandText = "SELECT statement goes here",
    Connection = conn
  } ;
  var reader = command.ExecuteReader();
  return reader.Read();
}

虽然它确实返回一个true / false值,指示sql查询是否检索了任何行,但它会使数据读取器,命令和连接挂起。

有些行等待在SqlDataReader上读取。

退出方法时,SqlCommand和SqlDataReader超出范围。他们最终将被垃圾收集,但直到他们这样做:

  • 连接已锁定,因为它具有正在执行的命令。这意味着在SqlCommand和SqlDataReader被Disposed和垃圾收集之前,没有其他人可以使用它。可能会有一段时间。

  • 您的SQL Server实例在连接的SPID上有挂起的读取,这意味着它具有出色的锁定。这最终会导致数据库中的阻塞,并且您的DBA会脾气暴躁。

SqlConnectionSqlCommand等等都是IDisposable。这意味着您可以与using一起使用以确保它们被妥善处理,并且当它们超出范围时,它们所拥有的所有资源都会被释放。此外,默认情况下会合并SqlConnection,这意味着您通常应该打开连接,执行并立即关闭,然后将其返回到池中以供其他用途。

所以......如果你要做的是检查数据库中是否存在条件,做这样的事情,利用上述内容。代码更清晰,你不会撕掉你的头发试图弄清楚为什么看似有鬼魂SPID浮动你的SQL服务器并阻止其他用户:

static bool ConditionExists( string someParameterValue )
{
  bool exists ; // our return value

  const string query = @"
    select convert(bit,sign(count(*)))
    from foo t
    where t.someColumn = @p1
    " ;
  string connectionString = GetConnectionString() ;

  using ( SqlConnection connection = new SqlConnection(connectionString) )
  using ( SqlCommand    cmd        = connection.CreateCommand() )
  {
    cmd.CommandText = query ;
    cmd.CommandType = CommandType.Text;
    connection.Open() ;
    exists = (bool) cmd.ExecuteScalar() ;
    connection.Close() ;
  }

  return exists ;
}

编辑注意: using不进行垃圾回收。 C#中的垃圾收集是非确定性的:系统决定垃圾收集器运行的时间和密集程度。 using确保IDisposable个对象在引用超出范围时调用其Dispose()方法。除非您在完成对象时显式地调用Dispose(),否则允许IDisposable释放它所拥有的资源,而Dispose() 最终将 < / em>在垃圾回收器清理对象实例时调用,这可能需要一段时间......同时,所保存的资源可能会导致其他对象/进程/等的问题。

虽然构造

using ( Widget foo = new Widget() )
{
  DoSomethingUseful() ;
}

[几乎] 完全等同于构造

Widget foo ;
try
{
  foo = new Widget() ;
  DoSomethingUseful() ;
}
finally
{
  foo.Dispose() ;
}

using范围变量除外),但为什么要进行所有额外的输入try / finally需要而不是简洁明了using