2016-04-27 65 views
3

因为我需要在特定的表行被删除之前,这将引发一些第三方审核更新一列“UpdatedBy”审计的目的。更新的实体框架之前,任何删除

我目前的解决办法是在我的上下文类来创建一个自定义的SaveChanges方法,但我删除的实体的任何改变我做被忽略,生成的SQL只是一个DELETE命令。

是否有可能同时触发的UPDATE和DELETE在SaveChanges方法的实体?

CS代码

public partial class MyContext : DbContext 
{ 
    public int SaveChanges(int userId) 
    { 
     foreach (var entry in ChangeTracker.Entries<Auditable>()) 
     { 
      if (entry.State == EntityState.Deleted) 
      { 
       entry.Entity.UpdatedBy = userId; 
      } 
     } 

     return base.SaveChanges(); 
    } 
} 

例SQL生成

DELETE FROM EntityTable 
WHERE Id = @00 

希望的SQL

UPDATE EntityTable 
SET UpdateBy = @00 
WHERE Id = @01 

DELETE FROM EntityTable 
WHERE Id = @01 

更新

为了澄清,我使用了第三方审计框架,它在单独的数据库中创建新行。在执行之前删除更新的目的是为了让单独的数据库来存储执行删除的用户ID。因此,尽管该行从原始数据库中删除,审计行需要创建,这是由UPDATE触发。

+1

但如果你更新任何东西然后删除它,那么为什么需要更新? 例如在表中的“A”更新“ROW1”,然后删除“ROW1”,所以“ROW1”将被卸下,那么为什么更新 – 2016-04-27 12:12:30

+0

有没有办法做到这一点,在EF单个事务。您将必须执行2个事务,一个更新,然后另一个执行删除。 – Igor

+0

如何在sql server中启用对该表的更改跟踪?如果你使用sql server。 – vendettamit

回答

2

实体框架不能被强制执行UPDATE以及DELETE,但我可以生成SQL来手动调用更新。并在事务中运行更改。

int SaveChangesWithDelete(int userId) 
    { 
     using (var tx= Database.BeginTransaction()) //Begin a new transaction 
     { 
      var entitiyGroups = ChangeTracker.Entries() 
       .Where(e => e.State == EntityState.Deleted && e.Entity is Auditable) 
       .Select(e => e.Entity) 
       .GroupBy(d => d.GetType(); 

      foreach (var entityGroup in entitiyGroups) //Loop through deleted entities and run a manual UPDATE 
      { 
       string query = string.Format(@" 
        UPDATE {0} SET UpdatedBy = {1} 
        WHERE Id IN ({2}) 
       ", entityGroup.Key.Name, userId, string.Join(",", entityGroup.Select(e => PrimaryKeyValue(e)))); 

       Database.ExecuteSqlCommand(query); //Execute the query - this triggers the audit framework 
      } 

      int result = SaveChanges();  //save the context changes as normal 
      tx.Commit();     //commit the transaction 
      return result;     //return the result 
     } 
    }