订单重复执行的问题

hornbills 2010-12-25 02:03:29
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

几万个订单会有一个重复出库,怎么回事?
...全文
428 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
hornbills 2011-02-24
  • 打赏
  • 举报
回复
用哪一级事务?
子夜__ 2011-02-24
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 hornbills 的回复:]

这个问题还没有解决,有具体解决方案吗?
[/Quote]

用事务。。
hornbills 2011-02-24
  • 打赏
  • 举报
回复
这个问题还没有解决,有具体解决方案吗?
archu 2010-12-26
  • 打赏
  • 举报
回复
我就不明白了,有一个重复出库跟事务又有什么关系?

重复出库只能说明有两个请求几乎同时做了出库这件事情,就算事务在第一行代码就启用,那就能阻止两个请求同时做一件事情了?

我猜测(由于不了解楼主的代码是如何实现的,所以只好猜测),在原本的业务逻辑里面,在执行dbo.UpdateOrderSaleStatus(OrderID, 10)之后,会把StatusID修改为非"1"的值,是这样吗?

如果是这样的话,那么我们假设有两个请求几乎同时进来对同一个订单做出库这件事情,执行到"If StatusID <> 1 Then"这一行的时候,两个请求都不满足条件,于是程序继续往下执行,因此最初出库两次。

如果前面的假设都成立的话,要避免这个问题只好做好同步了,但是做了同步又影响性能。呵呵。
  • 打赏
  • 举报
回复
嗯更正一下,lz的问题应该叫做“不可重复读”,而不是“脏读”。

脏读是指第一个事务还没有提交一个出库单时,另一个事务就以出库单为计算条件了;不可重复读则是指lz这种第二个事务读取第一个事务可能将来会修改的数据作为自己的计算条件的状况。

(我印象中)SQL Server默认的机制,可以避免不可重复读。而Oracle只能避免脏读,而不能避免不可重复读。
hornbills 2010-12-25
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 sp1234 的回复:]

引用 7 楼 hornbills 的回复:
我感觉到是这个问题,虽然几率很低,怎么才能避免使用脏数据呢?


对于SQL Server来说,你至少需要在 dbo.GetOrderSaleByID(OrderID) 这一条语句之前就开启事务。

SQL Server几乎是现在比较流行的商品化关系数据库中,默认的事务隔离级别最严格的一个数据库系统了。如果你使用其他事务隔离级别比较低级的关……
[/Quote]

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

这样会自动为订单表加锁吗?或者要手动加锁解锁?
wuyq11 2010-12-25
  • 打赏
  • 举报
回复
using(TransactionScope scope = new TransactionScope())
{
//方法1
//方法2:
scope.Complete();
}

  • 打赏
  • 举报
回复
[Quote=引用 7 楼 hornbills 的回复:]
我感觉到是这个问题,虽然几率很低,怎么才能避免使用脏数据呢?
[/Quote]

对于SQL Server来说,你至少需要在 dbo.GetOrderSaleByID(OrderID) 这一条语句之前就开启事务。

SQL Server几乎是现在比较流行的商品化关系数据库中,默认的事务隔离级别最严格的一个数据库系统了。如果你使用其他事务隔离级别比较低级的关系数据库系统(比如Oracle),那么即使是把你的所有代码一开始就启动事务也无法保证不会脏读,可以看看他们的产品的文档如何避免这类脏读。
hornbills 2010-12-25
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 sp1234 的回复:]

楼主并非没有使用什么事务,而是使用不当。

脏数据是数据库的一个基本概念。举个例子,假设我们向账户里存100元钱,那么你的程序是先取出原来的余额(比如1000元),然后将其更新为1100元?更新时才进行事务保护?那么显然如果你几乎同时去再存200元钱,结果并不是1300元,而是1100元或者1200元,用户就受到损失了!

这就是程序员错误地使用事务,它的程序用脏数据(即1000元钱余额……
[/Quote]
我感觉到是这个问题,虽然几率很低,怎么才能避免使用脏数据呢?
  • 打赏
  • 举报
回复
楼主并非没有使用什么事务,而是使用不当。

脏数据是数据库的一个基本概念。举个例子,假设我们向账户里存100元钱,那么你的程序是先取出原来的余额(比如1000元),然后将其更新为1100元?更新时才进行事务保护?那么显然如果你几乎同时去再存200元钱,结果并不是1300元,而是1100元或者1200元,用户就受到损失了!

这就是程序员错误地使用事务,它的程序用脏数据(即1000元钱余额)来带入事务操作,造成的。
啊兵 2010-12-25
  • 打赏
  • 举报
回复
使用事务操作吧。
wuyq11 2010-12-25
  • 打赏
  • 举报
回复
几条数据执行是否一样存在问题
执行过程中进度条
hookyzlr 2010-12-25
  • 打赏
  • 举报
回复
看不到具体sql,不好说啊,有可能是数据库事务没控制好吧
Rock870210 2010-12-25
  • 打赏
  • 举报
回复
并发。。。
Rock870210 2010-12-25
  • 打赏
  • 举报
回复
不会是并非的问题吧?虽然有事务支持!

62,041

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧