2017-06-08 116 views
0

我有一些entityFramework 4的麻煩。這裏是: 我們有一個SQL服務器數據庫。每個表都有3個而不是觸發器來插入,更新和刪除。 我們知道的EntityFramework有一些問題需要處理論文觸發器,這就是爲什麼我們在觸發器的末尾添加以下代碼強制根據rowCount:EF4 RowCount問題,而不是插入觸發器,而更新其他表

用於插入:

DECLARE @Identifier BIGINT; 
SET @Identifier = scope_identity() 
SELECT @Identifier AS Identifier 

用於更新/刪除:

CREATE TABLE #TempTable (temp INT PRIMARY KEY); 
INSERT INTO #TempTable VALUES (1); 
DROP TABLE #TempTable 

它工作得很好至今: 從不是INSERT觸發器(假設表A),我嘗試更新的其他表的字段(表B)

我知道我的更新代碼完美的工作,因爲手動插入完成工作。只有當我使用實體框架時纔會出現問題。

+0

哪個'scope_identity()'被插入觸發器返回?從看到這個孤立的代碼片段中看不清楚。那一刻插入的記錄是什麼? –

+1

你給了我你的問題的解決方案。在我而不是表B的更新觸發器中,我通過插入另一個表來記錄表的狀態歷史記錄。 我的錯誤是插入沒有被IF EXISTS包圍,第三張表上的插入在錯誤的時刻消耗了我的scope_identity()。 謝謝,你的幫助:) –

+0

嘿嘿,總是很棘手,這些觸發器。也許你可以把它變成答案,這樣人們會更容易找到解決方案。 –

回答

1

我現在有解決方案,讓我們用一個完整的例子來做一個這樣的學校案例。 :)

在這個例子中,我們的應用程序是一個地址簿。我們希望每次添加,更新或刪除該業務的聯繫人時更新業務活動(業務中的IsActive列) 。如果業務的至少一個聯繫人 處於活動狀態,則認爲該業務處於活動狀態。我們在表格中記錄企業的每個狀態變化,以獲得完整的歷史記錄。

所以,我們有3個表:

表業務(標識符(PK身份),姓名,IsActive), 表聯繫(標識符(PK身份),姓名,IsActive,IdentifierBusiness) 表BusinessHistory(標識符(PK身份),IsActive,日期,IdentifierBusiness)

這裏的是一個觸發我們感興趣的是:

表聯繫(觸發IoInsert):

-- inserting the new rows 
INSERT INTO Contact 
(
    Name 
    ,IsActive 
    ,IdentifierBusiness 
) 
SELECT 
    t0.Name 
    ,t0.IsActive 
    ,t0.IdentifierBusiness 
FROM 
    inserted AS t0 
-- Updating the business 

UPDATE 
    Business 
SET 
    IsActive = CASE WHEN 
      (
       (t0.IsActive = 1 AND Business.IsActive = 1) 
       OR 
       (t0.IsActive = 1 AND Business.IsActive = 0) 
      ) THEN 1 ELSE 0 
FROM 
    inserted AS t0 
WHERE 
    Business.Identifier = t0.IdentifierBusiness 
AND 
    t0.IsActive = 1 
AND 
    Business.IsActive = 0 



-- Forcing rowCount for EntityFramework 
DECLARE @Identifier BIGINT; 
SET @Identifier = scope_identity() 
SELECT @Identifier AS Identifier 

表業(觸發IoUpdate)

UPDATE 
    Business 
SET 
    IsActive = 1 
FROM 
    Contact AS t0 
WHERE 
    Business.Identifier = t0.IdentifierBusiness 
AND 
    t0.IsActive = 1 
AND 
    Business.IsActive = 0 


---- Updating BusinessHistory 

INSERT INTO BusinessHistory 
(
    Date 
    ,IsActive 
    ,IdentifierBusiness 
) 
SELECT 
    DATE() 
    ,t0.IsActive 
    ,t0.Identifier 
FROM 
    inserted AS t0 
INNER JOIN 
    deleted AS t1 ON t0.Identifier = t1.Identifier 
WHERE 
    (t0.Identifier <> t1.Identifier) 


-- Forcing rowCount for EntityFramework 
CREATE TABLE #TempTable (temp INT PRIMARY KEY); 
INSERT INTO #TempTable VALUES (1); 
DROP TABLE #TempTable 

表BusinessHistory:

-- Updating the business 

UPDATE 
    Business 
SET 
    IsActive = CASE WHEN 
      (
       (t0.IsActive = 1 AND Business.IsActive = 1) 
       OR 
       (t0.IsActive = 1 AND Business.IsActive = 0) 
      ) THEN 1 ELSE 0 
FROM 
    inserted AS t0 
WHERE 
    Business.Identifier = t0.IdentifierBusiness 
AND 
    t0.IsActive = 1 
AND 
    Business.IsActive = 0 

-- inserting the new rows 
INSERT INTO BusinessHistory 
(
    Date 
    ,IsActive 
    ,IdentifierBusiness 
) 
SELECT 
    DATE() 
    ,t0.IsActive 
    ,t0.Identifier 
FROM 
    inserted AS t0 

-- Forcing rowCount for EntityFramework 
DECLARE @Identifier BIGINT; 
SET @Identifier = scope_identity() 
SELECT @Identifier AS Identifier 

因此,概括地說,發生了什麼?

我們有2個表,商業和聯繫。聯繫人正在更新表插入和更新業務。

業務更新時,它插入到BusinessHistory中,當存儲更新的字段IsActive時,該表存儲表Business的更新歷史記錄 。

的事情是,即使我不插入BusinessHistory新行,我啓動插入指示等等,我去的,而不是插入的觸發器的表BusinessHistory內。當然,在這個結尾,有一個scope_identity()。您只能使用scope_identity一次,並且它會返回插入的最後一個標識。 因此,由於我沒有插入任何BusinessHistory,它正在消耗我新插入的聯繫人的scope_identity:聯繫人表的插入的 的scope_identity爲空!

如何隔離問題?

  • 使用分析器,你搞清楚,有在BusinessHistory插入指令時,它不應該有任何人。

  • 使用調試,你將最終結束在一個INSERT觸發器你不應該英寸

如何解決呢?

這裏有幾種選擇。我所做的是由假設條件表業務圍繞BusinessHistory的插入: 我想只插入插入如果statut「IsActive」發生了變化:

IF EXISTS 
(
    SELECT 
     1 
    FROM 
     inserted AS t0 
    INNER JOIN 
     deleted AS t1 ON t0.Identifier = t1.Identifier 
    WHERE 
     (t0.Identifier <> t1.Identifier) 
) 
BEGIN 
    INSERT INTO BusinessHistory 
    (
     Date 
     ,IsActive 
     ,IdentifierBusiness 
    ) 
    SELECT 
     DATE() 
     ,t0.IsActive 
     ,t0.Identifier 
    FROM 
     inserted AS t0 
    INNER JOIN 
     deleted AS t1 ON t0.Identifier = t1.Identifier 
    WHERE 
     (t0.Identifier <> t1.Identifier) 
END 

的另一種可能性是,在觸發而不是表BusinessHistory的插入,由IF包圍整個觸發EXISTS條件

IF EXISTS (SELECT 1 FROM inserted) 
BEGIN 
    ----Trigger's code here ! 
END 

如何避免呢?

  • 那麼,使用這些修復程序之一!
  • 在大多數情況下,避免scope_identity(),@@ IDENTITY已經足夠了!在我的公司,我們只使用EF_4的scope_identity!

我知道我的英語並不完美,如果它不夠好,我可以編輯,或者如果有人想在這個主題上添加一些東西!