代码中的交易

3
我遇到了一个问题,我不确定如何解决,想知道最佳方法以实现此任务。
我们正在开发一个VB.net 2.0和SQL 2005应用程序。用户可以基于可能包含许多收到货物的购买来取消接待。但是,在取消过程中,会向用户询问一些问题,例如“您是否要取消Good#1”。如果是,则删除。然后,“您是否要取消Good#2”,否则不要删除并且还有另一个问题(如果收到的项目已发出,则必须由用户手动进行处理)。最后,如果所有商品都成功取消,我们必须取消接待本身。但有时,如果在此过程中向用户提出错误或某些条件,我们希望取消从开始执行的任何操作,并将其恢复到其原始状态。因此,我考虑使用“事务”。
  1. 我知道可以使用SQL事务,并且我也知道如何使用它,但是我无法真正使用它,因为用户必须执行可能取消此事务的操作。

  2. 我还记得.NET 2.X及以上版本中的TransactionScope,它可以实现类似的功能,我也知道如何使用它。问题出现在TransactionScope和MSDTC上。使用这个时,我们仍然会收到一个错误信息,其中说:

已禁用分布式事务管理器(MSDTC)的网络访问。请使用组件服务管理工具在MSDTC的安全配置中启用网络访问的DTC。

我已经尝试了另一个堆栈帖子中描述的方法,效果很好... 直到用户重新启动他们的电脑。每次用户重新启动他们的电脑时,他们必须重新设置该值。而且,默认情况下,没有计算机将此值设置为开启状态。在至少有10台计算机上安装了这个程序,在其中没有一台被激活。所以,有人有什么想法可以实现这个吗?还有其他通过代码进行事务处理的方法可以使用吗?
注意1:我知道有些人会说,首先向用户询问条件并在内存中维护值。一旦完成,如果一切顺利,请进行删除。但是,如果在删除商品#4时出现错误怎么办?我如何给一个存储过程提供要删除的商品的动态列表?
注意2:对不起,我的英语通常是法语。
注意3:任何C#示例也可以提供,因为我知道VB和C#两种编程语言。

如果按照NOTE1的指示进行操作,将删除嵌入到事务中,并在出现错误时进行回滚。有关批处理中自动回滚的详细信息,请参阅SET XACT_ABORT ON - Nikola Markovinović
是的,但我仍然有一个问题,即我可能会从接收#A中取消Good #1、3、4、5、8。我如何将动态数组传递给存储过程?有什么办法吗? - Simon Dugré
在SQL Server中有XML数据类型,因此可以将各种内容作为XML参数传递。但是我认为您可以根据用户的操作构建自己的SQL语句,并“ExecuteNonQuery”此批处理。 - Nikola Markovinović
当前的操作对于每个商品在两个独立的表中执行2次更新,并在所有商品都被取消后一次性地执行2个存储过程。很难将其组织在同一个“ExecuteNonQuery”过程中... - Simon Dugré
1个回答

1

假设您已经有类似的存储过程来管理取消:

create proc CancelGood (@goodID int)
as
   SET NOCOUNT ON
   SET XACT_ABORT ON

   begin transaction

   update table1 set canceled = 1
    where GoodID = @GoodID

   update table2 set on_stock = on_stock + 1
    where GoodID = @GoodID

   commit transaction

如果用户选择“是”,VB代码将一个字符串添加到一些取消商品列表中。我不熟悉VB.Net;在C#中,它看起来像:

canceledGoods.Add (string.Format("exec dbo.CancelGood {0}", goodID));

然后,如果canceledGoods中至少有一个字符串,则构建并执行批处理:

batch = "BEGIN TRANSACTION" +
        " BEGIN TRY " +
        string.Join (Environment.NewLine, canceledGoods.ToArray()) + 
        " END TRY" +
        " BEGIN CATCH " +
        " -- CODE TO CALL IF THERE WAS AN ERROR" +
        "    ROLLBACK TRANSACTION" +
        "    RETURN" +
        " END CATCH" +
        " -- CODE TO CALL AFTER SUCCESSFULL CANCELATION OF ALL GOODS" +
        " COMMIT TRANSACTION"

conn.ExecuteNonQuery (batch);

这对于C#来说没问题,我之前只做过C#,所以我对两者都很熟悉。我会尝试你写的方法并稍后回来。但是,我的工作肯定有很多,因为我只解释了我的问题的一小部分。我必须尝试回想如何使用这些方法来解决问题。相对于SQL,我更熟悉.NET代码,所以可能更容易使用第二部分。 - Simon Dugré

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接