3

我正在使用 asp.net mvc 制作网站。我有一张看起来像这样的桌子

Create Table Items(
   [Id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
   [Colname] [nvarchar](20) NOT NULL
   //OTHER UNIMPORTANT COLS HERE
)

ALTER TABLE Items ADD CONSTRAINT UN_Colanme UNIQUE(Colname)

在我的网站上,我经常尝试创建新项目,或从数据库中选择项目(使用实体框架)。这是它在 c# 中的样子

var item = db.Items.FirstOrDefault(i => i.Colname == "foo");
if(item == null)
{
   item = new Item("foo");
   db.Items.Add(item);
}

//some stuff with item
db.SaveChanges();

有时,2 个请求同时进入,都试图创建具有相同 colname 的项目。虽然唯一约束防止数据库存储任何错误值,但尝试保存更改会引发异常,因为违反了约束。

捕获此异常是处理此异常的正常方法吗?如果不是上面的 c# 代码,而是创建一个锁定表的存储过程,然后仅在允许的情况下插入一个新行,然后返回该行,我能否获得良好的性能?是常做的吗?

4

2 回答 2

1

好吧,有很多方法可以做到这一点。我会说在这种情况下捕获异常是最便宜的。另一种方法是将事务隔离级别提高到更高的级别,例如 Serializable。

不过,在这种情况下,我会发现唯一的约束违规并继续。如果我们太从编程的角度去想,我们可以把这种情况想成双重检查锁定,我们检查,它不存在,然后进入事务,看到它存在,然后我们可以丢弃我们的值并使用在那里的那个。

于 2013-05-23T22:59:27.963 回答
0

这就是为什么许多开发人员使用 GUID 或 DB 分配的 Ints 作为唯一键的原因。如果您的外部密钥是合法分配的并且是逻辑重复,则使用您已演示的 DB 重复约束或考虑使用悲观锁。Sql server 有一个可以使用的工具。搜索示例和博客

  • 使用指导键
  • 使用 DB 分配的 Int 作为键
  • 使用列约束并捕获异常(如您所解释)
  • 使用悲观锁定,例如 SQL 内置功能

在网上搜索“SQL server sp_getapplock”以了解如何使用。

于 2013-05-23T23:49:02.680 回答