2

이것은 내 첫 번째 게시물이지만 내 문제에 대한 올바른 솔루션을 찾는 데 많은 도움이됩니다.INSTEAD OF INSERT 트리거가 Entity Framework의 SaveChanges에서 오류를 발생 함

삽입 된 데이터를 확인하기위한 INSTEAD OF INSERT 트리거가있는 테이블이있는 데이터베이스 (SQL Server 2008 R2)가 있습니다.

중복 행 인 경우 해당 행을 업데이트하십시오. 그렇지 않으면 해당 행을 삽입하십시오.

트리거 :

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 (엔티티 프레임 워크)이 작동하지 않습니다.

웹 서비스 (.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-table-having-instent-of-trigger-from-entity-data -틀 –

답변

3

트리거의 UPDATE 부분에 @@ identity를 설정해야한다고 생각합니다. 이렇게하려면 간단한 삽입 쿼리를 만들고 실행하십시오. 이 가정 MonitorSummary에 ID 열 id입니다 :

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 또는 당신이 변경된 기록의 목록을 검색하는 데 사용할 수있는 업데이트에 출력 조항이 새로운를 사용하는 경우.

Btw를 사용하면 존재하는 부분을 제거하고 UPDATE가 @@ rowcount를 0으로 설정했는지 확인할 수 있습니다. 그렇다면 행을 삽입해야합니다.