Lorsque vous utilisez Entity Framework, il utilise en interne la OUTPUT
technique 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 OUTPUT
valeurs, c'est que EF utilise également cette technique pour obtenir la rowversion
ligne nouvellement insérée.
Vous pouvez utiliser la concurrence optimiste dans vos modèles de structure d'entité en utilisant l' Timestamp
attribut: 🕗
public class TurboEncabulator
{
public String StatorSlots)
[Timestamp]
public byte[] RowVersion { get; set; }
}
Lorsque vous faites cela, Entity Framework aura besoin rowversion
de 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, Timetsamp
vous ne pouvez pas utiliser de OUTPUT
clause.
C'est parce que s'il y a un déclencheur sur la table, tout Timestamp
SORTIE 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 SELECT
est que vous ne pouvez pas SORTIR a rowversion
dans 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 UPDATE
sur une table avec un déclencheur, vous ne pouvez pas utiliser de OUTPUT
clause. Essayer de faire UPDATE
avec un OUTPUT
n'est pas pris en charge et donnera une erreur:
La seule façon de le faire est avec une SELECT
dé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 ().