我有一個場景,其中創建了一個可更新視圖,該視圖由多個使用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
由於上述表格和視圖定義中沒有包含外鍵約束,所以父記錄必須在我之前插入插入其他表中的記錄以保持參照完整性。
而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的樣品:
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
現在,執行在SSMS上述SQL語句正確地插入記錄進入各種表格。但是,它無法返回select中的任何內容,因爲SCOPE_IDENTITY()返回NULL。
所以,我不知道如何讓SCOPE_IDENTITY()返回插入到[Parent]表中的值,或者甚至是可能的。有誰知道這是否可以完成,或者如果我需要探索定義存儲過程來處理這種情況?或者還有其他建議嗎?
注:我要代表我的應用程序中的實體作爲「扁平化」的對象,而不是一個多對象組成......
您的代碼太長,無法讀取,尤其是您應該嘗試簡化它的SQL,因此它更容易理解和閱讀 –
感謝您的建議。我編輯了我原來的文章,以簡化應該更易於遵循的情景 –