2

這是我的第一篇文章,但我來這裏尋找解決我的問題的正確方法很多。INSTEAD OF INSERT觸發器在實體框架的SaveChanges中導致錯誤

我有一個數據庫(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(實體框架)不起作用。

我認爲這是無關緊要的,它在Web服務(.asmx)中工作,因爲我測試了EF與測試表(沒有觸發器),一切正常工作。

在此代碼中,我將一些對象添加到EF並保存更改。

已經嘗試保存在循環的變化,但是這也沒有影響......

private void StoreData(MonitorSummary[] data) 
{ 
    foreach (MonitorSummary item in data) 
    { 
     MonitorEntity.MonitorSummary.AddObject(item); 
     //MonitorEntity.SaveChanges(); 
    } 
    MonitorEntity.SaveChanges(); 
} 

我總是這個錯誤結束:

Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.

我也試圖Attach該對象並將併發模式更改爲固定, 所有這些都不起作用。

我甚至嘗試過一個AFTER INSERT觸發器,但這不是我想要的解決方案,因爲它已經插入表格中,所以我不得不編寫更多代碼。

現在有沒有人可以解決我的問題?

+0

我認爲你可以從這個線程得到答案: http://stackoverflow.com/questions/5820992/error-when-inserting-into-table-having-instead-of-trigger-from-entity-data -幀 – 2012-10-10 16:34:14

回答

3

我相信你需要在觸發器的UPDATE部分設置@@ identity。爲此,創建一個簡單的插入查詢並執行它。假設有標識列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或更高版本中有更新時,您可以使用它來檢索更改的記錄列表輸出條款。

順便說一句,你可能會刪除存在的部分,並檢查是否更新設置@@ rowcount爲零;如果是這樣,你需要插入行。

相關問題