• "There is already an open DataReader associated with this Command which must be closed first"错误


    其实这个错误跟LINQ To Sql没有必然的关系, 不过我觉得见到它的场景一般情况下都应该是用LINQ的时候.

    以下示例代码:

     1            try
     2            {
     3                dc.SubmitChanges();
     4                dc.sp1();
     5                tran.Commit();
     6            }

     7            catch (Exception ex)
     8            {
     9                tran.Rollback();
    10                Master.SetError(ex.Message);
    11                return;
    12            }

    如果在try块的前面dc上有select 动作, 并且存储过程sp1 中也有select动作, 则上述语句将抛出异常:
    There is already an open DataReader associated with this Command which must be closed first

    经过单步跟踪, 第一次是tran.Commit 先抛出异常, 被catch块捕捉, 执行tran.Rollback时再次抛出异常, 这里没有捕捉器了,整个程序于是异常. 如果仅仅是异常还算好事了, 由于LINQ 事务操作的时候, 是用排它锁锁定目标表的, 所以事务没有结束, 目标表就一直被锁定, 这里由于事务既无法提交也无法回滚, 所以目标表被锁死.

    看得出这个错误是毁灭性的.
    究其原因, 是因为默认情况下, 不允许返回多个dataSet, 如果不用LINQ的话, 我想基本上也不会需要返回多个dataset, 所以应该很少会碰到这个错误, 但是用linq的话,概率就很大了. 解决办法:
    1. 不要在存储过程中返回结果集.(貌似不太现实...)
    2. 给连接字符串加上"MultipleActiveResultSets=True"

    如果表已经被锁死, 解决办法:
    1. 重启SQL SERVER 服务
    2. 先在查询分析器上按ctrl+2 , 返回当前锁定的情况. 例如:

    spid dbid ObjId IndId Type Resource Mode Status
    51   5      0      0       DB                   X      GRANT

    找到Mode 带"X"的项的spid, 例如上面一行, spid是51, 在查询分析器中执行: KILL 51

    感觉不可理解的是为什么事务回滚也会抛出异常, 使得这个错误一旦发生后果就极其严重, 无论是何种初衷禁止返回多个结果集, 都不应该让表这样被锁死, 鄙视一下微软...

    ---------------------------------------------

    作者:夏狼哉
    博客:http://www.cnblogs.com/Moosdau

    如需引用,敬请保留作者信息,谢谢

  • 相关阅读:
    字王谈M1字形与个人云字库
    想让网站销量爆涨?你离成功只差一个出色的购物车设计
    学习JavaScript很吃力?开发五年经验带你轻松上路!
    摹客—— 自动生成你的颜色规范
    【求职,不求人】2019最全Web设计师面试问题,助你轻松拿下面试
    交易类APP原型设计分享
    全是宝!20款优质高效的在线协作工具任你挑,就是这么强大!
    灵感专题—2019年优秀网页设计作品赏析#4月
    2019年最实用的导航栏设计实践和案例分析全解
    摹客标注:自动标注一键生成,手动标注自由补充
  • 原文地址:https://www.cnblogs.com/Moosdau/p/1419575.html
Copyright © 2020-2023  润新知