如何构建此交易?

时间:2012-07-25 17:26:32

标签: c# asp.net sql-server transactions isolation-level

我们有一个基于ASP.NET / MSSQL的Web应用程序,可生成包含连续订单号的订单。

当用户保存表单时,将按如下方式创建新订单:

  1. SELECT MAX(order_number)FROM order_table,调用此max_order_number
  2. 设置new_order_number = max_order_number + 1
  3. 使用此new_order_number(它只是订单记录中的字段,而不是数据库密钥)插入新订单记录
  4. 如果我在单笔交易中附上上述3个步骤,如果两个客户同时保存新订单,是否会避免创建重复的订单号? (并且假设系统最终位于具有多个IIS服务器和一个MSSQL服务器的Web场中。)

    由于系统中某处的并发性,我想避免两个客户选择相同的MAX(order_number)。

    应该使用什么隔离级别?谢谢。

4 个答案:

答案 0 :(得分:5)

为什么不使用Identity作为订单号?

修改
据我所知,您可以将当前的order_number列设为Identity(您可能需要重置种子,因为我已经这样做了一段时间)。你可能想做一些测试 Here's很好地了解了在SSMS中将列更改为Identity时实际发生的情况。作者提到如果表已有数百万行,这可能需要一段时间。

答案 1 :(得分:1)

风险是在其中一个插入新订单之前选择MAX(order_number)的两个过程。更安全的方法是一步到位:

INSERT INTO order_table
(order_number, /* other fields */)
VALUES
( (SELECT MAX(order_number)+1 FROM order_table ) order_number,
  /* other values */
)

答案 2 :(得分:1)

我同意G_M;使用标识字段。添加记录时,只需

INSERT INTO order_table (/* other fields */)
VALUES (/* other fields */) ; SELECT SCOPE_IDENTITY()

Scope Identity的返回值将是您的订单号。

答案 3 :(得分:1)

使用身份是目前最好的主意。我像这样创建我的所有表:

CREATE TABLE mytable (
    mytable_id int identity(1, 1) not null primary key,
    name varchar(50)
)

"身份" flag表示,"让SQL Server为我分配这个号码"。 (1,1)表示身份号码应从1开始,每当有人将记录插入表格时,它将增加1。 Not Null意味着不允许任何人在此列中插入null,并且"主键"意味着我们应该在此列上创建clustered index。使用这种表格,您可以插入如下记录:

-- We don't need to insert into mytable_id column; SQL Server does it for us!
INSERT INTO mytable (name) VALUES ('Bob Roberts')

但是要回答你的字面问题,我可以就交易的运作方式提供一些教训。这样做肯定是可能的,尽管不是最佳的:

-- Begin a transaction - this means everything within this region will be 
-- executed atomically, meaning that nothing else can interfere.
BEGIN TRANSACTION
    DECLARE @id bigint

    -- Retrieves the maximum order number from the table
    SELECT @id = MAX(order_number) FROM order_table

    -- While you are in this transaction, no other queries can change the order table,
    -- so this insert statement is guaranteed to succeed
    INSERT INTO order_table (order_number) VALUES (@id + 1)

-- Committing the transaction releases your lock and allows other programs 
-- to work on the order table
COMMIT TRANSACTION

请记住,使用标识主键列声明您的表会自动为您完成此操作。