Quando você usa o Entity Framework, ele usa internamente a OUTPUT
técnica para retornar o valor de ID recém-inserido
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
Os resultados da saída são armazenados em uma variável de tabela temporária, unidos de volta à tabela e retornam o valor da linha da tabela.
Nota: Não tenho idéia de por que a EF uniria a tabela efêmera de volta à tabela real (em que circunstâncias as duas não coincidiriam).
Mas é isso que a EF faz.
Essa técnica ( OUTPUT
) está disponível apenas no SQL Server 2008 ou mais recente.
Editar - O motivo da associação
O motivo pelo qual o Entity Framework se une novamente à tabela original, em vez de simplesmente usar os OUTPUT
valores, é porque o EF também usa essa técnica para obter o valorrowversion
linha recém-inserida.
Você pode usar simultaneidade otimista em seus modelos de estrutura de entidade por usando o Timestamp
atributo: 🕗
public class TurboEncabulator
{
public String StatorSlots)
[Timestamp]
public byte[] RowVersion { get; set; }
}
Ao fazer isso, o Entity Framework precisará rowversion
da linha recém-inserida:
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 para recuperar isso, Timetsamp
você não pode usar umOUTPUT
cláusula.
Isso porque se houver um gatilho na mesa, qualquer Timestamp
OUTPUT que você estiver errado estará errado:
- Inserção inicial. Registro de data e hora: 1
- A cláusula OUTPUT gera o registro de data e hora: 1
- trigger modifica a linha. Registro de data e hora: 2
O registro de data e hora retornado nunca estará correto se você tiver um gatilho na mesa. Então você deve usar um separadoSELECT
.
E mesmo se você estava disposto a sofrer a conversão de linha incorreta, o outro motivo para realizar uma separação separada SELECT
é que você não pode OUTPUT a rowversion
em uma variável de tabela:
DECLARE @generated_keys table([Id] uniqueidentifier, [Rowversion] timestamp)
INSERT INTO TurboEncabulators(StatorSlots)
OUTPUT inserted.TurboEncabulatorID, inserted.Rowversion INTO @generated_keys
VALUES('Malleable logarithmic casing');
A terceira razão para fazê-lo é por simetria. Ao executar uma UPDATE
tabela com um gatilho, você não pode usar uma OUTPUT
cláusula. Tentando fazer UPDATE
com um OUTPUT
não é suportado e dará um erro:
A única maneira de fazer isso é com uma SELECT
declaração de acompanhamento :
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 (...)
, ou método mais antigo:INSERT INTO Table1(fields...) VALUES (...); SELECT SCOPE_IDENTITY();
você pode obtê-lo em c # usando ExecuteScalar ().