11

我已经看到这出现在代码中的几个地方,从来没有解释,只是在它上面的一个神秘的注释(声明和执行包括上下文的想法。它只是运行 SqlCommand 的标准过程):

//SqlCommand cmd = new SqlCommand();
//cmd.ExecuteReader();
//Read off the results

//Cancel the command. This improves query time.
cmd.Cancel ();

基本上,在完成查询后,它会返回并取消它,声称有一些性能提升。我想你可能会在它释放并释放 XmlReader 时取回一些内存,但通常无论如何它都会超出范围。

我以前从来没有打扰过它,但它最终出现在我正在审查的一些代码中。在代码中运行 SqlCommand 后取消它实际上会以某种方式加速它,还是这只是一些奇怪的程序员迷信?

4

4 回答 4

16

根据MSDN,这是正确的。

Close 方法填充输出参数、返回值和 RecordsAffected 的值,从而增加了关闭用于处理大型或复杂查询的 SqlDataReader 所需的时间。当返回值和受查询影响的记录数不重要时,可以通过在调用 Close 方法之前调用关联的 SqlCommand 对象的 Cancel 方法来减少关闭 SqlDataReader 所需的时间。

诡异的!

于 2010-08-17T19:11:11.650 回答
9

如果您的调用返回大量行,并且您没有读取所有行,则调用Cancel会带来潜在的MASSIVE 性能改进ExecuteReader

举例来说,假设一个查询返回一百万行,并且您在仅读取了前 1000 行后关闭了阅读器。如果Cancel在关闭阅读器之前调用失败,该Close方法将在内部枚举剩余的 999,000 行时阻塞

试试看!

于 2013-06-20T03:41:52.293 回答
0

我们在 Cinchcast 的技术团队进行了一些基准测试,我们发现添加 cmd.Cancel() 实际上会减慢速度。

我们有一个 DALC 调用,用于获取主持人的剧集列表。我们运行了 1000 次,得到了返回 10 集的平均响应时间。

所以返回 10 显示平均取消:0.069s 平均不取消:0.026s

返回 10 集时运行速度要慢得多。

所以,我再次尝试返回 100 集,看看更大的结果集是否会产生影响。

因此,每次通话返回 100 个节目平均取消:0.132s 平均不取消:0.122s

所以这一次时间上的差异要小得多。尽管在我们通常的用例中不使用取消,但它仍然更快。

于 2012-09-13T15:53:31.620 回答
0

在您的示例中,您打开阅读器,阅读所有行,然后取消命令,但您没有显示阅读器关闭的位置。

确保取消发生在/Dispose之前Close。例如,在此示例中您不会获得性能提升(不幸的是,生产中的真实代码):

using (var rdr = cmd.ExecuteReader (CommandBehavior.Default))
{
   retval = DocumentDir.DBRead (rdr);
}

// Optimization.  Allows reader to close more quickly.... NOT!
cmd.Cancel ();  // bad!

太糟糕了,它已经被 Using 语句关闭了!

这是它应该如何阅读以实现潜在的好处:

using (var rdr = cmd.ExecuteReader (CommandBehavior.Default))
{
   retval = DocumentDir.DBRead (rdr);

   // Optimization.  Allows reader to close more quickly.
   cmd.Cancel ();
}

MSDN SqlCommand.Cancel

在某些极少数情况下,如果您调用 ExecuteReader,然后在调用 Cancel 之前调用 Close(隐式或显式),然后调用 Cancel,则取消命令将不会发送到 SQL Server,并且在您调用 Close 后结果集可以继续流式传输. 为避免这种情况,请确保在关闭阅读器或连接之前调用 Cancel。

于 2014-08-14T00:06:05.660 回答