假设我有以下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吗?
由于
答案 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会脾气暴躁。
SqlConnection
和SqlCommand
等等都是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
?