使用transactionscope检索最大IDENTITY id

时间:2014-03-25 17:14:03

标签: c# asp.net dbcontext transactionscope

以下是代码:

using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
    DBContext.AddtoSomeTable(record);
    System.Threading.Thread.Sleep(5000);
    DBContext.SaveChanges();

    MAX_ID = (from t in DBContext.SomeTable
              select t.ID).Max();

    scope.Complete();
}

据我所知,在范围完成之前,MAX_ID应该是刚刚插入的新记录的ID。即使有两个用户同时提交,后一个用户应该等到第一个用户TransactionScope完成。

但是,会发生什么是两个用户得到相同的MAX_ID。这意味着在将第一个人的记录插入数据库之后,插入第二个人的记录,然后第一个人获得他的MAX_ID

我认为在事务中表被锁定以避免脏数据。有谁能解释一下?

编辑: ID字段自动递增

1 个答案:

答案 0 :(得分:1)

在操作期间会执行不同类型和范围的锁定,并且随着锁定数量的增加,锁定范围将因锁定升级而更改。如果在单个事务中,您在单个表中插入/更新/删除单行,则很可能会采用独占行锁。当您更新/插入/删除该表中的更多行时,一旦累积了一定数量的行锁,锁升级就会将它们提升为页锁。累积足够的页面锁定,您将升级到表锁。

我不知道您尝试使用select max(id) from someTable做什么,但是如果您希望它能反映您SaveChanges()操作刚才所做的事情,那么很可能,您是&#39 ;重新创造竞争条件。

假设您正在使用SQL Server,内置函数 scope_identity() 将为您提供

  

插入同一范围内的标识列的最后一个标识值。   范围是一个模块:存储过程,触发器,函数或批处理。"

但是:如果在同一范围内,您可以在两个不同的表中插入一行,每个表都有一个标识列,

begin transaction
insert foo () ...
insert bar () ...
commit transaction

scope_identity()为您提供范围生成的最后一个值(对于此示例中的表bar)。