Ich muss eine Methode zum Erstellen einer eindeutigen Bestellnummer erstellen. Jede Bestellnummer muss immer größer als die letzte sein, sie sollte jedoch nicht immer fortlaufend sein. Die Lösung muss in einer Webfarmumgebung funktionieren.Bestellnummer mit einer Stored-Prozedur erstellen auswählen und innerhalb einer Transaktion aktualisieren
Derzeit haben Sie eine gespeicherte Prozedur, die für das Abrufen einer neuen Bestellnummer verantwortlich ist, die so gesetzt werden muss, dass die Bestellnummer nicht fortlaufend ist. Die Anwendung wechselt jetzt von einem einzelnen Server zu einer Webfarm und daher ist die Kontrolle des Zugriffs auf die gespeicherte Prozedur über eine Sperre in C# als Methode zur Zugriffskontrolle nicht mehr möglich. Ich habe die gespeicherte Prozedur wie folgt aktualisiert, aber ich bin besorgt, dass ich blocks \ locks \ deadlocks einführen werde, wenn gleichzeitige Aufrufe auftreten.
der Tabelle und Indexstrukturen sind als
MyAppSetting Tabelle
CREATE TABLE [dbo].[MyAppSetting](
[SettingName] [nvarchar](255) NOT NULL,
[SettingValue] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_MyAppSetting] PRIMARY KEY CLUSTERED
(
[SettingName] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
Meine Bestellung Tisch
CREATE TABLE [dbo].[MyOrder](
[id] [int] IDENTITY(1,1) NOT NULL,
[OrderNumber] [nvarchar](50) NOT NULL CONSTRAINT [DF_MyOrder_OrderNumber] DEFAULT (N''),
... rest of the table
CONSTRAINT [PK_MyOrder] PRIMARY KEY NONCLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
Die SQL-Transaktion
Set Transaction Isolation Level Serializable;
Begin Transaction
--Gen random number
SELECT @Random = ROUND(((@HighSeed - @LowSeed -1) * RAND() + @LowSeed), 0)
--Get Seed
select @Seed = [SettingValue] FROM [MyAppSetting] where [SettingName] = 'OrderNumberSeed'
--Removed concurrency and not required as order numbe should not exceed the seed number
--select @MaxOrderNUmber = Max(OrderNumber) FROM MyOrder
--if @MaxOrderNumber >= @Seed Begin
-- Set @Seed = @MaxOrderNumber
--end
-- New Seed
Set @OrderNumber = @Seed + @Random
Update [MyAppSetting] Set [SettingValue] = @OrderNumber where [SettingName] = 'OrderNumberSeed'
select @OrderNumber
Commit
Fragen Sie, ob dies Deadlocks verursachen kann? Wenn dies der Fall ist, hängt die Antwort davon ab, was sonst noch auf diese Tabellen zugreift, aber ich glaube nicht, dass diese Prozedur sich selbst blockieren würde. Wenn Sie nachfragen, ob es bessere Möglichkeiten gibt, die Bestellnummer zu generieren, müssten Sie die Anforderung klarer beschreiben. – Rattle
Es scheint mir, dass dieses Skript eine Nebenläufigkeitsproblem hat. Ich denke, Sie müssen bvc_Order sperren, BEVOR Sie MAX erhalten und sperren, bis Sie die bvc_WebappSetting-Tabelle aktualisieren. – FLICKER
@Rattle, guter Punkt Ich habe meine Anforderungen hinzugefügt – Stig