Lorsque vous utilisez Entity Framework, il utilise en interne la OUTPUTtechnique pour renvoyer la valeur d'ID nouvellement insérée
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
Les résultats de sortie sont stockés dans une variable de table temporaire, rejoints à la table et renvoient la valeur de ligne hors de la table.
Remarque: Je n'ai aucune idée de la raison pour laquelle EF fusionnerait intérieurement la table éphémère à la table réelle (dans quelles circonstances les deux ne correspondraient-elles pas).
Mais c'est ce que fait EF.
Cette technique ( OUTPUT) n'est disponible que sur SQL Server 2008 ou plus récent.
Modifier - La raison de la jointure
La raison pour laquelle Entity Framework rejoint la table d'origine, plutôt que d'utiliser simplement les OUTPUTvaleurs, c'est que EF utilise également cette technique pour obtenir la rowversionligne nouvellement insérée.
Vous pouvez utiliser la concurrence optimiste dans vos modèles de structure d'entité en utilisant l' Timestampattribut: 🕗
public class TurboEncabulator
{
public String StatorSlots)
[Timestamp]
public byte[] RowVersion { get; set; }
}
Lorsque vous faites cela, Entity Framework aura besoin rowversionde la ligne nouvellement insérée:
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
Et pour récupérer cela, Timetsampvous ne pouvez pas utiliser de OUTPUTclause.
C'est parce que s'il y a un déclencheur sur la table, tout TimestampSORTIE sera faux:
- Insert initial. Horodatage: 1
- La clause OUTPUT génère l'horodatage: 1
- le déclencheur modifie la ligne. Horodatage: 2
L'horodatage renvoyé ne sera jamais correct si vous avez un déclencheur sur la table. Vous devez donc utiliser un autre SELECT.
Et même si vous vouliez subir une version de ligne incorrecte, l'autre raison pour effectuer une séparation distincte SELECTest que vous ne pouvez pas SORTIR a rowversiondans une variable de table:
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 troisième raison de le faire est la symétrie. Lorsque vous effectuez une opération UPDATEsur une table avec un déclencheur, vous ne pouvez pas utiliser de OUTPUTclause. Essayer de faire UPDATEavec un OUTPUTn'est pas pris en charge et donnera une erreur:
La seule façon de le faire est avec une SELECTdéclaration de suivi :
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 une méthode plus ancienne:INSERT INTO Table1(fields...) VALUES (...); SELECT SCOPE_IDENTITY();vous pouvez l'obtenir en c # en utilisant ExecuteScalar ().