【问题标题】:Linq To SQL: Prevent creation of duplicatesLinq To SQL:防止创建重复项
【发布时间】:2014-09-01 10:39:53
【问题描述】:

考虑以下简单的用户表

我想编写通过某些谓词返回用户的 Linq To SQL 代码,例如电子邮件地址,如果用户不存在,则创建用户。代码可能看起来像

User GetUser(String name, String email) {
    using (var context = new DataContext()) {
        User user = context.Users.FirstOrDefault(u => u.email.Equals(email));
        if (user != null)
            return user;
        user = new User() { name = name, email = email };
        context.Users.InsertOnSubmit(user);
        context.SubmitChanges();
        return user;
    }
}

代码可能会并行执行,但不应创建重复用户。

出于几个原因,我宁愿不为表创建 unique 约束。您是否看到任何可以使用 Linq To SQL 实现且无需接触数据库的替代方案?

【问题讨论】:

  • 你的代码不是已经在检查是否有重复吗?

标签: c# sql linq linq-to-sql


【解决方案1】:

使用TransactionScope(默认为Serializable隔离级别):

User GetUser(String name, String email) 
{
    using (var tran = new TransactionScope())
    {
        using (var context = new DataContext()) 
        {
            User user = context.Users.FirstOrDefault(u => u.email.Equals(email));
            if (user != null)
                return user;
            user = new User() { name = name, email = email };
            context.Users.InsertOnSubmit(user);
            context.SubmitChanges();

            tran.Complete();

            return user;
        }
    }
}

有关 LINQ to Sql 中的事务支持的更多信息:http://msdn.microsoft.com/en-us/library/bb386995

【讨论】:

  • 不会创建副本,而是会死锁。但至少它是安全的,并且与 L2S 一样好。
  • usr - 你能描述一个在这种情况下 OP 死锁的例子吗?
  • 是的,有冲突的情况。两个事务都读取和 S-lock,然后两个事务都尝试写入和 X-lock。经典的僵局。这正是没有 SERIALIZABLE 时会插入重复行的情况。
  • 我对此表示赞同。这是一个理智的解决方案。不过,它会从重试循环中受益。
猜你喜欢
  • 2014-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-08
相关资源
最近更新 更多