Quando si utilizza Entity Framework, utilizza internamente la OUTPUTtecnica per restituire il valore ID appena inserito
DECLARE @generated_keys table([Id] uniqueidentifier)
INSERT INTO TurboEncabulators(StatorSlots)
OUTPUT inserted.TurboEncabulatorID INTO @generated_keys
VALUES('Malleable logarithmic casing');
SELECT t.[TurboEncabulatorID ]
FROM @generated_keys AS g
JOIN dbo.TurboEncabulators AS t
ON g.Id = t.TurboEncabulatorID
WHERE @@ROWCOUNT > 0
I risultati dell'output vengono archiviati in una variabile di tabella temporanea, riuniti alla tabella e restituiscono il valore della riga dalla tabella.
Nota: non ho idea del motivo per cui EF si unirebbe di nuovo alla tabella effimera alla tabella reale (in quali circostanze i due non corrisponderebbero).
Ma è quello che fa EF.
Questa tecnica ( OUTPUT) è disponibile solo su SQL Server 2008 o versioni successive.
Modifica : il motivo del join
Il motivo per cui Entity Framework si ricollega alla tabella originale anziché utilizzare semplicemente i OUTPUTvalori è perché EF utilizza anche questa tecnica per ottenere la rowversionriga appena inserita.
È possibile utilizzare la concorrenza ottimistica nei modelli di framework dell'entità utilizzando l' Timestampattributo: 🕗
public class TurboEncabulator
{
public String StatorSlots)
[Timestamp]
public byte[] RowVersion { get; set; }
}
In questo caso, Entity Framework avrà bisogno rowversiondella riga appena inserita:
DECLARE @generated_keys table([Id] uniqueidentifier)
INSERT INTO TurboEncabulators(StatorSlots)
OUTPUT inserted.TurboEncabulatorID INTO @generated_keys
VALUES('Malleable logarithmic casing');
SELECT t.[TurboEncabulatorID], t.[RowVersion]
FROM @generated_keys AS g
JOIN dbo.TurboEncabulators AS t
ON g.Id = t.TurboEncabulatorID
WHERE @@ROWCOUNT > 0
E per recuperarlo Timetsampnon è possibile utilizzare una OUTPUTclausola.
Questo perché se c'è un trigger sul tavolo, qualsiasi TimestampOUTPUT sarà sbagliato:
- Inserimento iniziale Timestamp: 1
- Timestamp delle uscite della clausola OUTPUT: 1
- il trigger modifica la riga. Timestamp: 2
Il timestamp restituito non sarà mai corretto se si dispone di un trigger sul tavolo. Quindi è necessario utilizzare un separato SELECT.
E anche se eri disposto a subire una errata rowversion, l'altro motivo per eseguire un separato SELECTè che non puoi OUTPUT a rowversionin una variabile di tabella:
DECLARE @generated_keys table([Id] uniqueidentifier, [Rowversion] timestamp)
INSERT INTO TurboEncabulators(StatorSlots)
OUTPUT inserted.TurboEncabulatorID, inserted.Rowversion INTO @generated_keys
VALUES('Malleable logarithmic casing');
Il terzo motivo per farlo è per la simmetria. Quando si esegue un UPDATEsu una tabella con un trigger, non è possibile utilizzare una OUTPUTclausola. Provare a fare UPDATEcon an OUTPUTnon è supportato e genererà un errore:
L'unico modo per farlo è con una SELECTdichiarazione di follow-up :
UPDATE TurboEncabulators
SET StatorSlots = 'Lotus-O deltoid type'
WHERE ((TurboEncabulatorID = 1) AND (RowVersion = 792))
SELECT RowVersion
FROM TurboEncabulators
WHERE @@ROWCOUNT > 0 AND TurboEncabulatorID = 1
INSERT INTO Table1(fields...) OUTPUT INSERTED.id VALUES (...)o metodo precedente:INSERT INTO Table1(fields...) VALUES (...); SELECT SCOPE_IDENTITY();puoi ottenerlo in c # usando ExecuteScalar ().