避免重复的条目,而不是关键字段

时间:2013-07-17 14:37:27

标签: asp.net sql sql-server

我有一张桌子,有两列

key -> Primary Key, auto incremented
reqNumber -> This is a custom generated value

reqNumber的结构为年/月/日/数字,其中number是当天发出请求的次数。例如,如果今天发出了3个请求,昨天发出了2个请求,则该表将具有

key    reqNumber
1      2013/07/16/001
2      2013/07/16/002
3      2013/07/17/001
4      2013/07/17/002
5      2013/07/17/003

我遇到的问题是有时多个用户同时保存。执行保存的proc,首先检查今天创建了多少,然后再添加1,所以对于上面的内容,它会看到今天创建了3个,所以下一个将是4.之后它会插入。

但如果两个用户同时点击保存,则他们都获得4,这意味着当插入发生时,我得到2013/07/17/004两次。

有没有办法在SQL或.Net中避免这种情况?锁是唯一的方法,那些会降低性能的正确性吗?

3 个答案:

答案 0 :(得分:3)

如果您希望应用程序能够扩展,那么您将需要创建一个新表:

CREATE TABLE DayCounter (
    LastReset DateTime NOT NULL,
    NextValue INT NOT NULL
)

然后,您需要FUNCTION,以便随意获取下一个可用值:

CREATE FUNCTION NextCounter()
    RETURNS CHAR(3)
AS
BEGIN
    BEGIN TRANSACTION
        DECLARE @LastReset DATETIME
        DECLARE @NextValue INT

        SELECT @LastReset = LastReset FROM DayCounter
        IF (DATEPART(DAY, DATEADD(DAY, 1, @LastReset)) = DATEPART(DAY, GETDATE())
            UPDATE DayCounter SET LastReset = GETDATE(), NextValue = 1

        SELECT @NextValue = NextValue FROM DayCounter
        UPDATE DayCounter SET NextValue = NextValue + 1
    COMMIT TRANSACTION

    RETURN RIGHT('000' + CAST(@NextValue AS CHAR), 3)
END

所以现在你可以构建一个更新语句,将你的值串起来,但是它可以安全地从冲突管理每天的重置。

答案 1 :(得分:1)

首先,我会围绕选择和更新进行交易。

其次我只会使用乐观断开锁定(意为update table where key = TheKey and reqNumber = TheValueYouSelectedToCount)进行更新,并确保更新了一行。如果你有0行更新,这意味着其他人已经更新了它。

这样您就无法“松散”更新

答案 2 :(得分:1)

如果reqNumber必须是唯一的,那么数据库应该对列具有UNIQUE约束。添加此选项可为您提供另一种选择:在没有锁定的情况下尝试一次,如果插入失败,请使用锁定再次尝试。凭借高读/写比率和低冲突频率,这可以比每次交易的解决方案执行得更好。