INSTEAD OFトリガを使用するいくつかのテーブルで構成される更新可能なビューを作成したシナリオがあります。 SSMSを使用して手動でこのビューに挿入できることを確認しました。しかし、私のアプリケーションがビューを表現するためにEF Code-Firstを使用しているので、レコードを挿入しようとすると、EFが挿入ステートメントの後のSELECTでSCOPE_IDENTITY()を使用したために問題が発生します。私はscope_identity()のインクルードを「強制」するトリガの最後に文を含めようとしましたが、成功しませんでした。私はまた、幸運と私の挿入ステートメントにOUTPUTオプションを含めることを試みた。自分のシナリオがEFが処理するにはあまりにも複雑かどうか疑問に思っていますか?フィードバックに基づいてEFコードを使用して更新可能なビューを挿入/更新する方法
、私は非常に皆のために再現するのは簡単です何かにこのシナリオを簡素化しています:
関連するテーブルとビューの定義:
IF NOT EXISTS(SELECT * FROM [sysobjects] WHERE [type] = 'U' AND [name] = 'Parent')
BEGIN
CREATE TABLE [dbo].[Parent]
(
[ent_pk] INT IDENTITY(1,1) NOT NULL,
[ent_id] VARCHAR(25) DEFAULT('') NOT NULL,
CONSTRAINT [PK_Parent] PRIMARY KEY CLUSTERED ([ent_pk])
)
END
GO
IF NOT EXISTS(SELECT * FROM [sysobjects] WHERE [type] = 'U' AND [name] = 'Child1')
BEGIN
CREATE TABLE [dbo].[Child1]
(
[c1_entfk] INT NOT NULL,
[c1_field1] VARCHAR(30) DEFAULT('') NOT NULL,
[c1_fees] DECIMAL(7,2) DEFAULT(0) NOT NULL,
CONSTRAINT [PK_Child1] PRIMARY KEY CLUSTERED ([c1_entfk])
)
END
GO
IF EXISTS(SELECT * FROM sys.views WHERE [object_id] = OBJECT_ID(N'[dbo].[vwView]'))
DROP VIEW [dbo].[vwView]
GO
CREATE VIEW [dbo].[vwView] AS
SELECT [ent_pk],
[ent_id],
[c1_field1],
[c1_fees]
FROM [Parent]
LEFT JOIN [Child1] ON [c1_entfk] = [ent_pk]
GO
次のようにトリガー・コードは次のとおりです。
IF EXISTS(SELECT * FROM sysobjects WHERE [type] = 'TR' AND [name] = 'trg_vwView_i')
DROP TRIGGER [trg_vwView_i]
GO
CREATE TRIGGER [trg_vwView_i] ON [dbo].[vwView] INSTEAD OF INSERT
AS
BEGIN
INSERT INTO [Parent] ([ent_id])
SELECT [ent_id]
FROM [Inserted] [I]
INSERT INTO [Child1] ([c1_entfk], [c1_field1], [c1_fees])
SELECT [E].[ent_pk], [c1_field1], [c1_fees]
FROM [Inserted] [I]
INNER JOIN [Parent] [E] ON [E].[ent_id] = [I].[ent_id]
END
GO
上記の表とビューの定義に含まれていない外部キー制約のため、親レコードは最初に挿入する必要があります。参照整合性を維持するために、他のテーブル内のレコードをnsertingします。
そしてPOCOクラスの定義は次のとおりです。
[Table("vwView")]
public class SimpleViewTest
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ent_pk { get; set; }
[MaxLength(25)]
public string ent_id { get; set; }
[MaxLength(30)]
public string c1_field1 { get; set; }
public decimal c1_fees { get; set; }
}
挿入用EFによって生成されたSQLのサンプル:SSMSで上記のSQL文を実行
今exec sp_executesql N'INSERT [dbo].[vwView]([ent_id], [c1_field1], [c1_fees])
VALUES (@0, @1, @2)
SELECT [ent_pk]
FROM [dbo].[vwView]
WHERE @@ROWCOUNT > 0 AND [ent_pk] = scope_identity()',N'@0 nvarchar(25),@1 nvarchar(30),@2 decimal(7,2) ',@0=N'AK FED CU',@1=N'Alaska Federal Credit Union',@2=10.00
は、正しくレコードを挿入様々なテーブルに。しかし、SCOPE_IDENTITY()がNULLを返すため、selectには何も返されません。
私はSCOPE_IDENTITY()に[Parent]テーブルへの挿入の値を返す方法や、それが可能なのかどうかはわかりません。誰かがこれができるかどうか、あるいはこの種のシナリオを処理するストアドプロシージャの定義を探る必要があるかどうかを知っていますか?または、人々が持っている他の提案はありますか?
注:私は「フラット」オブジェクトではなく、複数のオブジェクトで構成される一つとして、自分のアプリケーション内のエンティティを表現したい...
あなたのコードはあまりにもSQLを読むのには時間がかかりすぎますので、簡単に理解して読んでください。 –
あなたの提案をありがとうございます。私はオリジナルの投稿を編集して、シナリオを簡素化し、それに従うのがずっと簡単になるはずです –