Entity Framework kullandığınızda OUTPUT
, yeni eklenen kimlik değerini döndürmek için tekniği dahili olarak kullanır
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
Çıktı sonuçları geçici bir tablo değişkeninde saklanır, tabloya geri eklenir ve satır değerini tablodan döndürür.
Not: EF'in neden geçici tabloyu gerçek tabloya geri birleştireceği hakkında hiçbir fikrim yok (bu koşullar altında ikisi eşleşmeyecektir).
Ama EF bunu yapar.
Bu teknik ( OUTPUT
) yalnızca SQL Server 2008 veya daha yenisinde kullanılabilir.
Düzenle - Katılma nedeni
Entity Framework'ün yalnızca OUTPUT
değerleri kullanmak yerine orijinal tabloyla birleşmesinin nedeni, EF'in rowversion
yeni eklenen bir satırı almak için de bu tekniği kullanmasıdır .
Şu özellik özelliğini kullanarakTimestamp
varlık çerçevesi modellerinizde iyimser eşzamanlılık kullanabilirsiniz : 🕗
public class TurboEncabulator
{
public String StatorSlots)
[Timestamp]
public byte[] RowVersion { get; set; }
}
Bunu yaptığınızda, Entity Framework'ün rowversion
yeni eklenen satırın olması gerekir:
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
Ve bu almak üzere Timetsamp
size edemez bir kullanma OUTPUT
şartı.
Çünkü masada bir tetikleyici Timestamp
varsa, OUTPUT ürününüz yanlış olur:
- İlk kesici uç. Zaman damgası: 1
- OUTPUT yan tümcesi çıktı zaman damgası: 1
- tetikleyici satırı değiştirir. Zaman damgası: 2
Tabloda bir tetikleyiciniz varsa , döndürülen zaman damgası hiçbir zaman doğru olmaz. Yani gerekir ayrı kullanın SELECT
.
Ve yanlış satır döngüsüne maruz kalmaya istekli olsanız bile, ayrı bir SELECT
işlem yapmanın diğer nedeni, rowversion
bir tablo değişkenine a OUTPUT alamamanızdır :
DECLARE @generated_keys table([Id] uniqueidentifier, [Rowversion] timestamp)
INSERT INTO TurboEncabulators(StatorSlots)
OUTPUT inserted.TurboEncabulatorID, inserted.Rowversion INTO @generated_keys
VALUES('Malleable logarithmic casing');
Bunu yapmanın üçüncü nedeni simetri için. Bir yaparken UPDATE
tetikleyici içeren bir tablo üzerinde, sen olamaz bir kullanma OUTPUT
şartı. A UPDATE
ile yapmayı denemek OUTPUT
desteklenmez ve bir hata verir:
Bunu yapmanın tek yolu bir takip SELECT
ifadesidir:
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 (...)
veya daha eski bir yöntem:INSERT INTO Table1(fields...) VALUES (...); SELECT SCOPE_IDENTITY();
ExecuteScalar () kullanarak c # içinde alabilirsiniz.