【问题标题】:SqlDataReader - result set cached?SqlDataReader - 结果集缓存?
【发布时间】:2009-05-28 14:19:42
【问题描述】:

当您使用 SqlDataReader 时,返回集是否完全由 ExecuteReader 步骤确定,或者您是否可以通过在读取时写入源表来影响您获得的结果?这是一个非常粗略的伪代码示例。

sc = new SqlCommand("select * from people order by last, first",db) ;
sdr = sc.ExecuteReader() ;

while (sdr.read())
{
    l = (string) sdr["last"] ;
    k = (string) sdr["key"] ;
    if (l.Equals("Adams")) 
    {
       sc2 = new SqlCommand("update people set last = @nm where key = @key") ;
       sc2.Parameters.Add(new SqlParameter("@nm", "Ziegler"));
       sc2.Parameters.Add(new SqlParameter("@key", k));
       sc2.ExecuteNonQuery() ;
    }
}

我在其他环境中看到了很多由于写入您正在读取的表而导致的严重错误。这里记录 k 从列表的顶部 (Adams) 被撞到底部 (Ziegler)。我假设(哈!)SqlDataReader 是免疫的。真的?假的?

【问题讨论】:

    标签: c# sql-server sqldatareader


    【解决方案1】:

    这取决于您的transaction isolation level 或其他锁定提示,但 iirc 默认情况下从 sql server 中的表读取会锁定这些记录,因此您发布的代码将死锁(sc2 最终将超时)或更新将去进入事务日志,在您的阅读器完成之前不会写入任何内容。我不记得我的头上是哪个。

    【讨论】:

    • 据我所知,我的实际实现运行良好。它确实更新了记录,因此表没有被锁定,但我没有更改会影响排序顺序的字段。
    • 听起来像第二次:更新保存在事务日志中。那或者您在某处设置了较弱的隔离级别。
    【解决方案2】:

    我看到的一个问题是,当阅读器打开时,它拥有数据库连接,当阅读器打开时,没有其他东西可以使用它。所以唯一可能的方法是使用不同的数据库连接,它仍然取决于事务级别

    【讨论】:

    • 我确实使用了单独的数据库连接。
    【解决方案3】:

    如果你想假设读取的数据没有被这些更新改变,你能不能把数据读到一个临时对象容器中,然后在完成所有读取之后,然后做你的更新?这会让问题变得没有意义。

    当然,从“这到底是如何工作的”的角度来看,我确实觉得这个问题很有趣。

    【讨论】:

      【解决方案4】:

      如果您想在迭代查询结果时进行更新,您可以将其全部读入 DataSet。

      我知道你没有问这个问题,而且我也知道这是伪代码,但请务必将你的 sc、sdr 和 sc2 变量包装在 using () 语句中,以确保它们被正确处理。

      【讨论】:

        猜你喜欢
        • 2011-01-06
        • 1970-01-01
        • 1970-01-01
        • 2013-08-09
        • 1970-01-01
        • 2017-07-20
        • 1970-01-01
        • 2017-07-03
        相关资源
        最近更新 更多