Ich verwende Dapper auf ADO.NET. Im Moment mache ich folgendes:
using (IDbConnection conn = new SqlConnection("MyConnectionString")))
{
conn.Open());
using (IDbTransaction transaction = conn.BeginTransaction())
{
// ...
Es gibt jedoch verschiedene Ebenen von Transaktionen, die festgelegt werden können. Ich denke das sind die verschiedenen Einstellungen.
Meine erste Frage ist, wie setze ich die Transaktionsebene (wo verwende ich Dapper)?
Meine zweite Frage ist, was ist die richtige Ebene für jeden der folgenden Fälle? In jedem dieser Fälle haben wir mehrere Instanzen eines Web-Worker (Azure) -Diensts ausgeführt, der gleichzeitig die DB trifft.
Welche Transaktion verwende ich für den Zugriff, der die verarbeitete Spalte aktualisiert? Und welche Transaktion verwende ich für den anderen Zugriff, der nur überprüfen muss, dass der Datensatz aktiv ist?
In diesem Fall ist es in Ordnung, wenn ein Konflikt dazu führt, dass die Gebühr nicht ausgeführt wird (wir bekommen sie am nächsten Tag). Aber es ist wichtig, dass wir jemanden nicht doppelt belasten. Und es ist kritisch, dass das Lesen, um zu überprüfen, dass der Datensatz aktiv ist, sofort erfolgreich ist, während die andere Operation in ihrer Transaktion ist.
Aber es ist der Schlüssel, dass die Platte konsistent bleibt. Und dies schließt den Anwendungsfall von "set NumUses = NumUses + @ParamNum" ein, so dass das Lesen, Berechnen und Schreiben des Spaltenwerts als eine atomare Aktion behandelt werden muss. Und wenn ich 3 Spaltenwerte setze, werden alle zusammen geschrieben.
1) Unter der Annahme, dass der Fakturierungsprozess ein SP mit mehreren Anweisungen ist, ist es am besten, eine andere "Sperr" -Tabelle zu erstellen, um die Tatsache zu speichern, dass der Fakturierungsauftrag bereits ausgeführt wird, z
CREATE TABLE InvoicingJob( JobStarted DATETIME, IsRunning BIT NOT NULL )
-- Table will only ever have one record
INSERT INTO InvoicingJob
SELECT NULL, 0
EXEC InvoicingProcess
ALTER PROCEDURE InvoicingProcess
AS
BEGIN
DECLARE @InvoicingJob TABLE( IsRunning BIT )
-- Try to aquire lock
UPDATE InvoicingJob WITH( TABLOCK )
SET JobStarted = GETDATE(), IsRunning = 1
OUTPUT INSERTED.IsRunning INTO @InvoicingJob( IsRunning )
WHERE IsRunning = 0
-- job has been running for more than a day i.e. likely crashed without releasing a lock
-- OR ( IsRunning = 1 AND JobStarted <= DATEADD( DAY, -1, GETDATE())
IF NOT EXISTS( SELECT * FROM @InvoicingJob )
BEGIN
PRINT 'Another Job is already running'
RETURN
END
ELSE
RAISERROR( 'Start Job', 0, 0 ) WITH NOWAIT
-- Do invoicing tasks
WAITFOR DELAY '00:01:00' -- to simulate execution time
-- Release lock
UPDATE InvoicingJob
SET IsRunning = 0
END
2) Lesen Sie, wie Transaktionen funktionieren: https://docs.microsoft.com/en-us/sql/t-sql/language-elements/transactions-transact-sql?view=sql-server-2017
Deine zweite Frage ist ziemlich weit gefasst.