EF4中的并发 - 如何有条件地创建实体

时间:2011-04-27 12:35:50

标签: c# .net entity-framework entity-framework-4 entity-framework-4.1

我需要能够创建一个新的用户实体,只有提供的电子邮件是唯一的。

我之前通过在if (!UserSet.Any(...))之前执行一个简单的AddToUserSet(...)来处理此问题。但是,这不是一个并发的解决方案,并且会在重负载下中断。

我一直在研究交易,但AFAIK我也需要在SELECT上设置UPDLOCK,但EF4不支持此功能。

其他人如何处理这个问题?

2 个答案:

答案 0 :(得分:1)

除了您的支票外,您还可以直接在数据库上的电子邮件字段中添加unique constraint

答案 1 :(得分:1)

您可以通过在事务中包含SELECT来强制锁定:

using (var scope = new TransactionScope())
{
    // Create context
    // Check non existing email
    // Insert user
    // Save changes
}

如果你想要插入的并发解决方案,这将使用你需要的可序列化事务 - UPDLOCK不足以确保在你的事务中不添加新记录。

这可能是一个非常糟糕的瓶颈所以我同意@paolo:只需将唯一约束放在数据库中,并在插入期间捕获异常,如果电子邮件不是唯一的。

来自Books online的可序列化交易:

  

指定以下内容:

    Statements cannot read data that has been modified but not yet  
    committed by other transactions.

    No other transactions can modify data that has been read by the  
    current transaction until the current transaction completes.

    Other transactions cannot insert new rows with key values that
    would fall in the range of keys read by any statements in the current
    transaction until the current transaction completes.
     

范围锁定位于与之匹配的键值范围内   每个陈述的搜索条件   在交易中执行。这块   来自更新或的其他交易   插入符合条件的任何行   对于任何执行的语句   当前的交易。这意味着   如果任何一个陈述   交易执行一秒钟   那时候,他们会读同一套   行。范围锁保持到   交易完成。这是   最严格的隔离   级别,因为它锁定整个范围   按键并保持锁直到   交易完成。因为   并发性较低,请使用此选项   只在必要时。这个选项有   与设置HOLDLOCK的效果相同   所有SELECT语句中的所有表   交易。