2

これは私の最初の投稿ですが、問題の適切な解決策を見つけるためにここによく来ます。

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 (エンティティ フレームワーク) が機能しないことです。

これが 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、または delete ステートメントが予期しない数の行 (0) に影響を与えました。エンティティが読み込まれてから、エンティティが変更または削除された可能性があります。ObjectStateManager エントリを更新します。

また、オブジェクトに対して同時実行モードを固定に変更しようとしましAttachたが、すべてが機能しません..

トリガーも試しましたAFTER INSERTが、それは私が望んでいた解決策ではなく、すでにテーブルに挿入されているため、さらに多くのコードを作成する必要があります..

誰かが今私の問題を解決していますか?

4

1 に答える 1

3

トリガーの UPDATE 部分に @@identity を設定する必要があると思います。そのためには、単純な挿入クエリを作成して実行します。idMonitorSummary に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 以降を使用している場合、UPDATE に出力句があり、変更されたレコードのリストを取得するために使用できます。

ところで、存在する部分を削除して、UPDATE が @@rowcount をゼロに設定しているかどうかを確認することができます。その場合は、行を挿入する必要があります。

于 2012-05-03T15:07:26.293 に答える