zoukankan      html  css  js  c++  java
  • 关于事务的一个问题

    本篇作为事务运用时的一个小知识,废话不多说,直接入题了。

    这里先抛一个问题,下面是我起初写的代码:

    View Code
     1 //开始事务
    2 SqlTransaction transaction = conn.BeginTransaction();
    3
    4 //创建命令对象
    5 SqlCommand command = new SqlCommand();
    6
    7 //事务和连接绑定同一个命令
    8 command.Connection = conn;
    9 command.Transaction = transaction;
    10 try
    11 {
    12 string strSql = "Select Top 1 Id, OrderId,C_Name,C_Mtel,C_Address From Pro_Order_List";
    13 //注意这里必须传入SqlTransaction的实例对象
    14 //注意这里使用了新的命令对象
    15 SqlDataReader dataReader = new SqlCommand(strSql, conn, transaction).ExecuteReader();
    16 while (dataReader.Read())
    17 {
    18 if (dataReader["OrderId"] != null || dataReader["OrderId"] != DBNull.Value)
    19 {
    20 //更新商品表,这里为测试用,没有实际业务意义
    21 command.CommandText = "Update Order_Pro_List Set OrderId = OrderId where OrderId = "
    22 + dataReader["OrderId"].ToString();
    23
    24
    25 command.ExecuteNonQuery();
    26 }
    27 }
    28
    29 //关闭dataReader
    30 dataReader.Close();
    31 //提交事务
    32 transaction.Commit();
    33 }
    34 catch
    35 {
    36 //事务回滚
    37 transaction.Rollback();
    38 }
    39 finally
    40 {
    41 //释放资源
    42 transaction.Dispose();
    43 transaction = null;
    44 }

    通过上面代码可以看出:我首先从订单表查询出一笔数据,然后通过Read()方法,循环读取,并同时更新商品表中的订单号。

    但这段代码在执行更新时一直报错,其错误内容为:

    $exception    {"已有打开的与此命令相关联的 DataReader,必须首先将它关闭。"}       System.Exception {System.InvalidOperationException}

    但我在执行读取返回SqlDataReader对象时使用的是新的命令对象,而执行事务的命令并没有与执行DataReader的命令相关联。

    纠错方向:

    1.代码是否有问题,于是让同事检验,并在他的电脑上跑,结果他那边可以运行。

    2.本地数据库是否有问题,通过下面的语句,查得版本如下:

    View Code
    1 SELECT '产品版本' = SERVERPROPERTY('productversion'), 
    2 '产品级别' = SERVERPROPERTY ('productlevel'),
    3 '版本' = SERVERPROPERTY ('edition')

    数据库是2005精简版,但找了些资料并没有发现什么问题。

    因为时间原因没有找到原因,希望园子里高手帮我看看!!!本人现在这里谢过了。

    以下是一个解决方法(暂且用着):

    方法很简单,就是重新建立一个连接,用这个连接来创建事务对象,而执行查询订单的语句用原来的连接。

    View Code
     1 //创建一个新的连接
    2 SqlConnection ConnTran = CommFun.CreateConn();
    3 //连接打开
    4 ConnTran.Open();
    5 //使用新连接开始事务
    6 SqlTransaction transaction = ConnTran.BeginTransaction();
    7 //创建命令对象
    8 SqlCommand command = new SqlCommand();
    9
    10 //新的连接和事务绑定同一个命令对象
    11 command.Connection = ConnTran;
    12 command.Transaction = transaction;
    13 try
    14 {
    15 string strSql = "Select Top 1 Id, OrderId,C_Name,C_Mtel,C_Address From Pro_Order_List";
    16 //这里使用旧的连接执行查询,不用事务控制
    17 SqlDataReader dataReader = new SqlCommand(strSql, conn).ExecuteReader();
    18 while (dataReader.Read())
    19 {
    20 if (dataReader["OrderId"] != null || dataReader["OrderId"] != DBNull.Value)
    21 {
    22 //更新商品表,这里为测试用,没有实际业务意义
    23 command.CommandText = "Update Order_Pro_List Set OrderId = OrderId where OrderId = "
    24 + dataReader["OrderId"].ToString();
    25
    26 command.ExecuteNonQuery();
    27 }
    28 }
    29 //关闭dataReader
    30 dataReader.Close();
    31 //提交事务
    32 transaction.Commit();
    33 }
    34 catch
    35 {
    36 //事务回滚
    37 transaction.Rollback();
    38 }
    39 finally
    40 {
    41 //释放资源
    42 transaction.Dispose();
    43 transaction = null;
    44 //新连接关闭
    45 ConnTran.Close();
    46 }


    -------------------------------------------------------------结束-----------------------------------------------------------------------

  • 相关阅读:
    可复用的WPF或者Silverlight应用程序和组件设计(1)——应用程序级别
    优化网站设计(一):减少请求数
    可复用的WPF或者Silverlight应用程序和组件设计(5)——布局重用
    演讲时经常用到的几个小工具介绍
    谈一谈职业素养
    优化网站设计(三):对资源添加缓存控制
    可复用的WPF或者Silverlight应用程序和组件设计(4)——外观级别
    如何在ViewModel中正确地使用Timer(定时器)
    一把锋利的匕首:利用数据绑定语法糖为Flash应用提供富JS接口
    一句话总结.Net下struct和class内存分配方面的区别
  • 原文地址:https://www.cnblogs.com/willpan/p/2236097.html
Copyright © 2011-2022 走看看