Cuando usa Entity Framework, usa internamente la OUTPUTtécnica para devolver el valor de ID recién insertado
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
Los resultados de salida se almacenan en una variable de tabla temporal, se unen de nuevo a la tabla y devuelven el valor de fila de la tabla.
Nota: No tengo idea de por qué EF uniría internamente la tabla efímera a la tabla real (en qué circunstancias los dos no coincidirían).
Pero eso es lo que hace EF.
Esta técnica ( OUTPUT) solo está disponible en SQL Server 2008 o posterior.
Editar : el motivo de la unión
La razón por la que Entity Framework se une a la tabla original, en lugar de simplemente usar los OUTPUTvalores, es porque EF también usa esta técnica para obtener la rowversionfila recién insertada.
Puede usar la concurrencia optimista en los modelos de marco de su entidad utilizando el Timestampatributo: 🕗
public class TurboEncabulator
{
public String StatorSlots)
[Timestamp]
public byte[] RowVersion { get; set; }
}
Cuando haga esto, Entity Framework necesitará rowversionla nueva fila insertada:
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
Y para recuperar esto Timetsampno puede usar una OUTPUTcláusula.
Esto se debe a que si hay un disparador en la mesa, cualquier Timestampsalida que realice estará mal:
- Inserción inicial. Marca de tiempo: 1
- La cláusula OUTPUT emite la marca de tiempo: 1
- el disparador modifica la fila. Marca de tiempo: 2
La marca de tiempo devuelta nunca será correcta si tiene un activador en la tabla. Entonces debes usar un separado SELECT.
E incluso si estuviera dispuesto a sufrir la versión incorrecta de la fila, la otra razón para realizar una separación SELECTes que no puede SALIR una rowversionvariable de tabla:
DECLARE @generated_keys table([Id] uniqueidentifier, [Rowversion] timestamp)
INSERT INTO TurboEncabulators(StatorSlots)
OUTPUT inserted.TurboEncabulatorID, inserted.Rowversion INTO @generated_keys
VALUES('Malleable logarithmic casing');
La tercera razón para hacerlo es por simetría. Al realizar un UPDATEsobre una mesa con un disparador, no puede usar una OUTPUTcláusula. Intentar hacer UPDATEcon un OUTPUTno es compatible, y dará un error:
La única forma de hacerlo es con una SELECTdeclaración de seguimiento :
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 un método anterior:INSERT INTO Table1(fields...) VALUES (...); SELECT SCOPE_IDENTITY();puede obtenerlo en C # usando ExecuteScalar ().