你可以在不同的对象直接共享你的sqlconnection,这样就解决了另外一个方法是使用serviced component中的分布式事务,编程很简单,性能不如上面一种方法

解决方案 »

  1.   


     我觉得这样的编程需求是很常见的,比如我在一个Project中定义了一个Class专门用来 操作数据,如方法
    public DataTable GetTable(string sDbConStr,string sGetFieldSQL)
    ---通过传入连接字符串和查询的SQL语句,返回一个结果集public bool  UpdateData(string sDbConStr,string sSQL)
    ---通过传入连接字符串和更新的SQL语句,来更新数据
    这样的话我就不要在操作数据库中书写大片重复的代码来操作数,而直需一条SQL就可以了
      但这样我就碰到了上面的关于事物的操作!
    特别,我在一个Form上保存一个结果时需要保存两个表,一个表的保存是在这个Form中完成的,但是另一个表的保存我却是调用放在此Form上的一个自己写的UserControl的Save方法来保存的,怎么把对这两个表的操作封装到一个数据库事物中呢? 急需解决
      

  2.   

    ripper(rIPPER):
    你说的serviced component我不知道是各什么东东,但
    共享sqlconnection是可以,但cmdPub.Transaction = myTrans还是没办法设置啊除非你让我把cmdPub共享,这样也不好吧!另外 共享sqlconnection也是不可行的,比如我上面说的在UserControl中的数据库操作 ,
      

  3.   

    我觉得你说的问题不存在呀,既然你已经把Connect封装了,你完全可以连事务也封装进你的类
    我觉得可以只样
    public DataTable GetTable(string sDbConStr,string sGetFieldSQL)
    {
      //开始事务
      //运行
      //提交事务
    }
      

  4.   

    to Yang_Wenli(Yang_Wenli):这怎么行呢? 我是要把“多次(个)调用 UpdateData(string sDbConStr,string sSQL),即多次执行UpdateData操作封装在一个事物中) 
      

  5.   

    再说详细一点,举个例子:
      
      我要在一个保存操作中要更新三个不同的Table——执行三次更新语句(Update) 这三个Update对应的更新语句分别为 UpdSQl1,UpdSQl2,UpdSQl3
    则我在保存事件中必须 连续三次调用Class的UpdateData方法
    Procedure Void Save(sDbConStr)
    {
       UpdateData(sDbConStr,UpdSQl1);
       UpdateData(sDbConStr,UpdSQl2);
       UpdateData(sDbConStr,UpdSQl3);}
    请问如何解决!?不要叫我修改CLass的UpdateData的方法,然后使此方法能一次传入一个SQL语句数组(比如把上面的UpdSQl1,UpdSQl2,UpdSQl3做为一个字符书数组传入)
    然后在UpdateData中定义事物,并逐个取出UpdSQl3执行。
      

  6.   

    仅供参考:
    产生连接CNN
    BEGIN传给模块SAVE(CNN,SAVEDATASTRING,......)
    .
    .
    .
    .
    END
    把UpdateData(string sDbConStr,string sSQL)改为UpdateData(数据连接对象 cnnObject,string sSQL)
      

  7.   

    楼上说的还是不行! 类似cmdPub.Transaction = myTrans; 的语句还是无法“解决”
      

  8.   

    因为cmdPub是在UpdateData内的,而myTrans不可能定义在UpdateData内!
      

  9.   

    我给大家一点思路:对于非返回提交,我写了一个方法,放在Util类中public static void Execute(string aSqlStr, SqlTransaction aTrans)
    {
       if (aTrans.Connection == ConnectionState.Closed)
       {
          aTrans.Connection.Open();
       }   Try
       {
         SqlCommand cmd = new SqlCommand(aSqlStr, aTrans.Connection, aTrans);
         cmd.ExecuteNonQuery();
    //这里不要提交事物
       }
       catch(Exception e)
      {
        throw e;
    //这里不要rollback
      }
    }
    以上是方法ok,以下是在类中的调用public void AddItem(Item aItem)
    {
      if (conn.State == ConnectionState.Closed)
      {
       conn.Open();
      }
       
      SqlTransaction aTrans = conn.BeginTransaction(IsolationLevel.ReadCommited, "AddItem");try
    {
      string aSqlStr = "";//要提交的语句  Util.Execute(aSqlStr, aTrans);  aSqlStr= "";//更多现一事物中的sql
      Util.Execute(aSqlStr, aTrans);  aTrans.Commit();//提交
    }
    catch(Exception e)
    {
      aTrans.RollBack("AddItem");
      throw e;
    }
    finally
    {
      conn.Close();
    }
    }这样可以保证所有该方法内的提交在同事务中,不会出现问题。以上仅个人之见,请指正,不适用于有参数的SqlCommand, sql
      

  10.   

    to  dreammaster(天涯) :  你测试过你的方法能保证事物性吗?可能你没看我前面的讨论吧, 我开始的想法和你是一样的,也是这样  做的,但根本未能起到事物的作用。
    Delphi这样就可以了!
    我也想这样Ok
      

  11.   

    to wenzm(疯之驴) 在我的程序中大量采用了这种方法,经实验完全可以控制事务,你的为什么不行呢?是不是中间存在什么差别?
      

  12.   

    wenzm(疯之驴) 我是要把“多次(个)调用 UpdateData(string sDbConStr,string sSQL),即多次执行UpdateData操作封装在一个事物中)
    这不简单么
    你可以过载
    UpdateData(string sDbConStr, string sSQL, SqlTranasaction aTrans)只要aTrans是统一的,他们就一定在同一个事物内,你的为什么不行,如果你的UpdateData方法调一下提交一下,你又怎么能保证他们多次执行在同事务下,我的方法已经在实际中大量应用,决没有问题.
      

  13.   

    dreammaster(天涯)方法非常好,可行,我要想达到的就是这个目的! 虽然麻烦一点,但比未能事物总是好。我现在做的一个有关流程的东西,因为设计到太多的表的操作,特别,很多对表的操作又被封装在了不同的类模块中,如果不能事物,其出错几率太大了,如不用事物,根本无法进入实际运行 。 我其实原来做的和你一样,但就是没有想到把Trans作为参数传入到UpdateData中,有的时候,一个人埋头苦想,很容易进入死胡同,技术性的东西,特别是编码方面的,看来还非得多多交流不可,个人总是有自己的思维定是。
    收益非浅! 非常感谢!