Ошибка при вставке в таблицу вместо триггера из структуры данных объекта
Я использую Entity Framework 4, при вставке новой записи с использованием Entity Framework в таблицу, которая имеет вместо триггера вставки, в то время как таблица имеет столбец идентификаторов, вместо триггера используется для изменения одного из вставленных значений в соответствии с определенной логикой,Entity Framework вызывает исключение "Оператор Store update, insert или delete затронул неожиданное количество строк (0). Возможно, объекты были изменены или удалены с момента загрузки объектов. Обновить записи ObjectStateManager".
Может ли кто-нибудь помочь, как обойти это исключение?
4 ответа
Используя Entity Framework 4.1, решение, опубликованное Ladislav для добавления Select of 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
Изменить для обработки вычисленных значений (спасибо Крису Моргану в комментариях):
Если у вас есть другие вычисленные значения в таблице, вам нужно будет включить их и в SELECT. Например, если у вас был CreatedDate
столбец, который использует GETDATE()
Вы бы сделали выбор следующим образом:
SELECT [AddressId], [CreatedDate] from [dbo].Addresses where @@ROWCOUNT > 0 and AddressId = scope_identity();
Вместо триггера выполняется операция вставки, созданная структурой Entity. Это может быть потенциальной проблемой, потому что после того, как вы используете столбец идентификации, за каждой вставкой следует:
select [Id]
from [dbo].[TableXXX]
where @@ROWCOUNT > 0 and [Id] = scope_identity()
Таким образом, вопрос в том, что происходит с этим запросом после замены вставки. Если он выполняется и возвращает ноль, вы получаете исключение. Вы можете добавить его после того, как вставите запись в свой триггер, но это не поможет, если исходный запрос также будет выполнен.
Вы можете изменить свой триггер до или после вставки и изменения данных.
Вам также необходимо вернуть любые свойства, помеченные как вычисленные
select [Id], [YourComputedColumn]
from [dbo].[TableXXX]
where @@ROWCOUNT > 0 and [Id] = scope_identity()
Я также обнаружил, что для StoreGeneratedPattern необходимо установить значение Identity, чтобы оно работало со столбцом nvarchar, который я использовал в качестве первичного ключа, но который не генерировал значение идентификатора. Это было для ситуаций триггера после вставки, который вычислял уникальное значение для хранения в ключевом столбце. В других ситуациях (добавление и обновление) может потребоваться установить значение Computed.