Триггер INSTEAD OF INSERT вызывает ошибку в SaveChanges Entity Framework
Это мой первый пост, но я прихожу сюда много, чтобы найти правильные решения для моих проблем.
У меня есть база данных (SQL Server 2008 R2) с таблицей, которая имеет INSTEAD OF INSERT
триггер для проверки вставленных данных.
Если это дублированная строка, обновите эту строку; в противном случае вставьте этот ряд.
Спусковой крючок:
ALTER TRIGGER [dbo].[CheckDataTrigger]
ON [dbo].[MonitorSummary]
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT OFF
IF exists( select * from inserted i, MonitorSummary ms
where ms.ServiceUrl = i.ServiceUrl
AND ms.AppName = i.AppName
AND ms.BuildVersion = i.BuildVersion
AND ms.FunctionName = i.FunctionName
AND ms.Company = i.Company
AND ms.UserName = i.UserName
AND ms.ServerName = i.ServerName)
BEGIN
UPDATE MonitorSummary
SET MonitorSummary.Function_Count = inserted.Function_Count,
MonitorSummary.Execution_Time_Sum = inserted.Execution_Time_Sum,
MonitorSummary.LogLevel = inserted.LogLevel
FROM inserted
WHERE MonitorSummary.ServiceUrl = inserted.ServiceUrl
AND MonitorSummary.AppName = inserted.AppName
AND MonitorSummary.BuildVersion = inserted.BuildVersion
AND MonitorSummary.FunctionName = inserted.FunctionName
AND MonitorSummary.Company = inserted.Company
AND MonitorSummary.UserName = inserted.UserName
AND MonitorSummary.ServerName = inserted.ServerName
END
ELSE
BEGIN
INSERT INTO MonitorSummary
SELECT
i.ServiceUrl, i.EmailAdress, i.EmailSent, i.AppName, i.BuildVersion,
i.FunctionName, i.Company, i.UserName, i.ServerName, i.Function_Count,
i.Execution_Time_Sum, i.LogLevel
FROM inserted i
END
SELECT Monitor_Id
FROM MonitorSummary
WHERE @@ROWCOUNT > 0 AND Monitor_Id = SCOPE_IDENTITY()
END
Как вы видете, SET NOCOUNT OFF
и я делаю запрос выбора в конце триггера. Дополнительная информация о столе:
CREATE TABLE [dbo].[MonitorSummary](
[Monitor_Id] [int] IDENTITY(1,1) NOT NULL,
[ServiceUrl] [nvarchar](100) NULL,
[EmailAdress] [nvarchar](100) NULL,
[EmailSent] [bit] NOT NULL default 0,
[AppName] [nvarchar](100) NULL,
[BuildVersion] [nvarchar](100) NULL,
[FunctionName] [nvarchar](100) NULL,
[Company] [nvarchar](100) NULL,
[UserName] [nvarchar](100) NULL,
[ServerName] [nvarchar](100) NULL,
[Function_Count] [int] NOT NULL default 0,
[Execution_Time_Sum] [numeric](18, 8) NOT NULL default 0,
[LogLevel] [nvarchar](50) NULL,
PRIMARY KEY CLUSTERED
(
[Monitor_Id] ASC
)
Я проверил триггер, прежде чем использовать его. это прекрасно работает!
Тестовый код:
INSERT INTO MonitorSummary VALUES
('ServiceUrl2', 'EmailAdress2', 0, 'AppName2', 'BuildVersion2', 'FunctionName2',
'Company2', 'UserName2', 'ServerName2', 1, 1, 'LogLevel2'),
('ServiceUrl2', 'EmailAdress2', 0, 'AppName2', 'BuildVersion2', 'FunctionName2',
'Company3', 'UserName2', 'ServerName2', 1, 1, 'LogLevel2'),
('ServiceUrl3', 'EmailAdress3', 0, 'AppName2', 'BuildVersion2', 'FunctionName2',
'Company2', 'UserName2', 'ServerName2', 1, 1, 'LogLevel2'),
('ServiceUrl3', 'EmailAdress3', 0, 'AppName2', 'BuildVersion2', 'FunctionName2',
'Company2', 'UserName2', 'ServerName2', 2, 2, 'LogLevel2')
СЕЙЧАС проблема в том, что EF (Entity Framework) не работает.
Я думаю, что не имеет значения, что это работает в веб-сервисе (.asmx), потому что я тестировал EF с тестовой таблицей (без триггера), и все просто отлично работает.
В этом коде я добавляю некоторые объекты в EF и сохраняю изменения.
Уже пытались сохранить изменения в цикле, но на это это никак не влияет...
private void StoreData(MonitorSummary[] data)
{
foreach (MonitorSummary item in data)
{
MonitorEntity.MonitorSummary.AddObject(item);
//MonitorEntity.SaveChanges();
}
MonitorEntity.SaveChanges();
}
Я всегда заканчиваю эту ошибку:
Оператор хранения, обновления или удаления затронул неожиданное количество строк (0). Объекты могут быть изменены или удалены с момента загрузки объектов. Обновите записи ObjectStateManager.
Я также пытался Attach
объект и изменить режим параллелизма на фиксированный, все это не работает..
Я даже попробовал AFTER INSERT
триггер, но это не то решение, которое я хотел, и я должен кодировать намного больше, так как он уже вставлен в таблицу..
У кого-нибудь сейчас есть решение моей проблемы?
1 ответ
Я считаю, что вам нужно установить @@identity в части UPDATE триггера. Для этого создайте простой запрос вставки и выполните его. Предполагая, что есть столбец идентичности id
в MonitorSummary:
declare @strSql varchar(1000)
declare @id int
select @id = max (id)
from MonitorSummary
where -- whole join condition to identify changed record(s)
set @strSql = 'SELECT Identity (Int, ' + Cast(@id As Varchar(10)) + ',1) AS id
INTO #Tmp'
EXECUTE (@strSql)
Если вы используете Sql Server 2005 или новее, в UPDATE есть предложение вывода, которое вы можете использовать для получения списка измененных записей.
Кстати, вы можете удалить существующую часть и проверить, если UPDATE устанавливает @@rowcount в ноль; если это так, вам нужно вставить строки.