Когда вы используете Entity Framework, он внутренне использует OUTPUTтехнику для возврата вновь вставленного значения идентификатора.
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
Выходные результаты сохраняются во временной табличной переменной, присоединяются обратно к таблице и возвращают значение строки из таблицы.
Примечание: я понятия не имею, почему EF внутренне присоединяет эфемерную таблицу обратно к реальной таблице (при каких обстоятельствах эти две пары не совпадают).
Но это то, что делает EF.
Этот метод ( OUTPUT) доступен только в SQL Server 2008 или новее.
Редактировать - причина присоединения
Причина, по которой Entity Framework присоединяется к исходной таблице, а не просто использует OUTPUTзначения, заключается в том, что EF также использует эту технику для получения rowversionновой вставленной строки.
Вы можете использовать оптимистичный параллелизм в моделях вашей сущности, используя Timestampатрибут: 🕗
public class TurboEncabulator
{
public String StatorSlots)
[Timestamp]
public byte[] RowVersion { get; set; }
}
Когда вы сделаете это, Entity Framework потребуется rowversionтолько что вставленная строка:
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
И для того, чтобы получить это, Timetsampвы не можете использовать OUTPUTпункт.
Это потому, что если на столе есть триггер, любой Timestampваш ВЫХОД будет неверным:
- Начальная вставка. Отметка времени: 1
- Предложение OUTPUT выводит временную метку: 1
- триггер изменяет строку. Отметка времени: 2
Возвращенная временная метка никогда не будет правильной, если у вас есть триггер на столе. Поэтому вы должны использовать отдельный SELECT.
И даже если вы захотите перенести неправильную версию строки, другая причина для выполнения отдельной процедуры SELECTсостоит в том, что вы не можете ВЫХОДИТЬ rowversionв переменную таблицы:
DECLARE @generated_keys table([Id] uniqueidentifier, [Rowversion] timestamp)
INSERT INTO TurboEncabulators(StatorSlots)
OUTPUT inserted.TurboEncabulatorID, inserted.Rowversion INTO @generated_keys
VALUES('Malleable logarithmic casing');
Третья причина сделать это для симметрии. При выполнении UPDATEтаблицы с триггером вы не можете использовать OUTPUTпредложение. Попытка сделать UPDATEс OUTPUTне поддерживается, и даст ошибку:
Единственный способ сделать это с последующим SELECTзаявлением:
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 (...)или более старый метод:INSERT INTO Table1(fields...) VALUES (...); SELECT SCOPE_IDENTITY();вы можете получить его в c #, используя ExecuteScalar ().