我正在使用Entity Framework 4,在使用Entity Framework插入一条新记录到一个包含触发器的表时,该表有一个自增列。如果表有一个Instead of Insert触发器,用于根据某些逻辑修改插入的值,则Entity Framework会引发异常“存储更新、插入或删除语句影响了意外数量的行数(0)。实体可能已经被修改或删除自从实体被加载以来,请刷新ObjectStateManager条目”。有人能帮忙解决这个异常吗?
使用Entity Framework 4.1,Ladislav发布的解决方案在触发器的末尾添加了Select Scope_Identity()语句,这对我解决了问题。为了完整起见,我在此处复制了整个触发器创建过程。使用这个触发器定义,我能够使用context.SaveChanges()向表中添加行。
ALTER TRIGGER [dbo].[CalcGeoLoc]
ON [dbo].[Address]
INSTEAD OF INSERT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT OFF;
-- Insert statements for trigger here
INSERT INTO Address (Street, Street2, City, StateProvince, PostalCode, Latitude, Longitude, GeoLoc, Name)
SELECT Street, Street2, City, StateProvince, PostalCode, Latitude, Longitude, geography::Point(Latitude, Longitude, 4326), Name
FROM Inserted;
select AddressId from [dbo].Address where @@ROWCOUNT > 0 and AddressId = scope_identity();
END
修改以处理计算值(感谢评论中的Chris Morgan):
如果表格中还有其他的计算值,你也需要在SELECT语句中将它们包括在内。例如,如果你有一个使用GETDATE()
函数的CreatedDate
列,你应该这样写SELECT语句:
SELECT [AddressId], [CreatedDate] from [dbo].Addresses where @@ROWCOUNT > 0 and AddressId = scope_identity();
SELECT [AddressId], [CreatedDate] from [dbo].Addresses where @@ROWCOUNT > 0 and AddressId = scope_identity();
- Chris Morgan代替触发器在Entity Framework创建的插入操作之前执行。这可能是一个潜在的问题,因为一旦您使用标识列,每个插入操作都会被以下操作所跟随:
select [Id]
from [dbo].[TableXXX]
where @@ROWCOUNT > 0 and [Id] = scope_identity()
所以问题是,一旦插入被替换后,这个查询会发生什么。如果它被执行并返回null,你会得到一个异常。你可以在触发器中插入记录后添加它,但如果原始查询也被执行,这将不起作用。同时,您还需要返回任何标记为计算属性(Computed)的属性。
select [Id], [YourComputedColumn]
from [dbo].[TableXXX]
where @@ROWCOUNT > 0 and [Id] = scope_identity()