EF4 RowCount问题,而不是插入触发器,而更新其他表

问题描述:

我有一些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

嘿嘿,总是很棘手,这些触发器。也许你可以把它变成答案,这样人们会更容易找到解决方案。 –

我现在有解决方案,让我们用一个完整的例子来做一个这样的学校案例。 :)

在这个例子中,我们的应用程序是一个地址簿。我们希望每次添加,更新或删除该业务的联系人时更新业务活动(业务中的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!

我知道我的英语并不完美,如果它不够好,我可以编辑,或者如果有人想在这个主题上添加一些东西!