If e.CommandName = "CheckOut" Then
            Dim dbw As New DBWarehouse
            Dim dbo As New DBOrderSale
            Dim dt As New DataTable
            Dim OrderID, StatusID As Integer
            
            '获取操作的订单号
            OrderID = e.CommandArgument
            dt = dbo.GetOrderSaleByID(OrderID)            '得到订单状态
            StatusID = dt.Rows(0).Item("StatusID")
            
            '如果不是新订单,退出
            If StatusID <> 1 Then
                lblMessage.Text = "订单状态不符!"
                Exit Sub
            End If
            Try
                '建立事务
                Using scope As New TransactionScope()
                    '订单内容添加到库存变化
                    dbw.AddWarehouseFromOrderSale(OrderID)
                    '订单状态修改为已出库
                    dbo.UpdateOrderSaleStatus(OrderID, 10)
                    scope.Complete()
                End Using
            Catch
            End Try
            BindGridView()
         End if几万个订单会有一个重复出库,怎么回事?

解决方案 »

  1.   

    看不到具体sql,不好说啊,有可能是数据库事务没控制好吧
      

  2.   


    对于SQL Server来说,你至少需要在 dbo.GetOrderSaleByID(OrderID) 这一条语句之前就开启事务。SQL Server几乎是现在比较流行的商品化关系数据库中,默认的事务隔离级别最严格的一个数据库系统了。如果你使用其他事务隔离级别比较低级的关系数据库系统(比如Oracle),那么即使是把你的所有代码一开始就启动事务也无法保证不会脏读,可以看看他们的产品的文档如何避免这类脏读。
      

  3.   

    using(TransactionScope scope = new TransactionScope())
    {
    //方法1   
    //方法2:   
    scope.Complete();
    }   
     
      

  4.   


    Using scope As New TransactionScope()
      '得到订单状态
      dt = dbo.GetOrderSaleByID(OrderID)
      StatusID = dt.Rows(0).Item("StatusID")
        
      '如果不是新订单,退出
      If StatusID <> 1 Then
      lblMessage.Text = "订单状态不符!"
      Exit Sub
      End If  '订单内容添加到库存变化
      dbw.AddWarehouseFromOrderSale(OrderID)
      '订单状态修改为已出库
      dbo.UpdateOrderSaleStatus(OrderID, 10)
      scope.Complete()
    End Using这样会自动为订单表加锁吗?或者要手动加锁解锁?
      

  5.   

    嗯更正一下,lz的问题应该叫做“不可重复读”,而不是“脏读”。脏读是指第一个事务还没有提交一个出库单时,另一个事务就以出库单为计算条件了;不可重复读则是指lz这种第二个事务读取第一个事务可能将来会修改的数据作为自己的计算条件的状况。(我印象中)SQL Server默认的机制,可以避免不可重复读。而Oracle只能避免脏读,而不能避免不可重复读。
      

  6.   

    我就不明白了,有一个重复出库跟事务又有什么关系?重复出库只能说明有两个请求几乎同时做了出库这件事情,就算事务在第一行代码就启用,那就能阻止两个请求同时做一件事情了?我猜测(由于不了解楼主的代码是如何实现的,所以只好猜测),在原本的业务逻辑里面,在执行dbo.UpdateOrderSaleStatus(OrderID, 10)之后,会把StatusID修改为非"1"的值,是这样吗?如果是这样的话,那么我们假设有两个请求几乎同时进来对同一个订单做出库这件事情,执行到"If StatusID <> 1 Then"这一行的时候,两个请求都不满足条件,于是程序继续往下执行,因此最初出库两次。如果前面的假设都成立的话,要避免这个问题只好做好同步了,但是做了同步又影响性能。呵呵。