当您使用实体框架时,它在内部使用OUTPUT 技术来返回新插入的 ID 值
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。
您可以通过using the Timestamp attribute: 在您的实体框架模型中使用乐观并发 ?
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 你的 OUTPUT 都会出错:
- 初始插入。时间戳: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 子句。不支持尝试使用 OUTPUT 执行 UPDATE,并且会报错:
做到这一点的唯一方法是使用后续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