C# 扩展基本类型并自动更新实体的审核信息

C# 扩展基本类型并自动更新实体的审核信息,c#,algorithm,entity-framework,.net-3.5,C#,Algorithm,Entity Framework,.net 3.5,我有一个实体模型,每个表上都有审计信息(50多个表) 目前,我们正在按计划更新审计信息 例: 但我正在寻找一个更自动化的解决方案。在保存更改期间,如果创建/更新了实体,我希望在将这些字段发送到数据库进行存储之前自动更新这些字段 有没有关于我如何做到这一点的建议?我宁愿不做任何反射,所以使用文本模板也不是不可能的 有人提出了一种解决方案来覆盖SaveChanges并在那里执行,但为了实现这一点,我要么使用反射(我不想在其中执行),要么派生一个基类。假设我沿着这条路走下去,我将如何实现这一点 比如说

我有一个实体模型,每个表上都有审计信息(50多个表)

目前,我们正在按计划更新审计信息

例:

但我正在寻找一个更自动化的解决方案。在保存更改期间,如果创建/更新了实体,我希望在将这些字段发送到数据库进行存储之前自动更新这些字段

有没有关于我如何做到这一点的建议?我宁愿不做任何反射,所以使用文本模板也不是不可能的

有人提出了一种解决方案来覆盖SaveChanges并在那里执行,但为了实现这一点,我要么使用反射(我不想在其中执行),要么派生一个基类。假设我沿着这条路走下去,我将如何实现这一点

比如说

EXAMPLE_DB_TABLE
 CODE
 NAME
 --Audit Tables
 CREATE_DATE
 CREATE_USER
 UPDATE_DATE
 UPDATE_USER
如果我创建一个基类

 public abstract class IUpdatable{

     public virtual DateTime CreateDate {set;}
     public virtual string CreateUser { set;}
     public virtual DateTime UpdateDate { set;}
     public virtual string UpdateUser { set;}
 }
最终目标是能够做一些像

   public overrride void SaveChanges(){
        //Go through state manager and update audit infromation
        //FOREACH changed entity in state manager
        if(entity is IUpdatable){
           //If state is created... update create audit.
           //if state is updated... update update audit
        }
   }

但是我不确定如何生成扩展接口的代码。

是的,我认为您可以这样做。总的想法是

public interface IAuditable
{
    void SetInsertedOn(DateTime date);
    void SetInsertedBy(string user);
    void SetUpdatedOn(DateTime date);
    void SetUpdatedBy(string user);
}

public partial class ExampleDBtable: EntityObject, Audit.IAuditable
{
     //Normal EDMX stuff here..
     public static ExampleDBtable CreateExampleDBtable(int id, string code, string name, DateTime insertedOn, string insertedBy, DateTime updatedOn, string updatedBy)
       {

       }
       //Extension points.
    #region IAuditable Members

    public void SetInsertedOn(DateTime date)
    {
        this._InsertedOn = date;
    }

    public void SetInsertedBy(string user)
    {
        this._InsertedBy = user;
    }

    public void SetUpdatedOn(DateTime date)
    {
        this._UpdatedOn = date;
    }

    public void SetUpdatedBy(string user)
    {
        this._UpdatedBy = user;
    }

    #endregion

    }
  • 处理
  • 在这种情况下,调用(EntityState.Modified)

  • 迭代结果并设置属性(如果需要)

  • 看。这类任务的解决方案非常好。

    通过数据库触发器“标记”更新的行不是更简单吗?数据库中提供的信息是否不够充分?(数据库用户与操作系统用户)

    这是最终的解决方案

    我基本上检查我的模型是否存在4个属性。如果实体包含

    InsertedOn和InsertedBy和UpdatedOn和UpdatedBy生成(使用tt文件)以下实现IAuditable接口的实体

    public interface IAuditable
    {
        void SetInsertedOn(DateTime date);
        void SetInsertedBy(string user);
        void SetUpdatedOn(DateTime date);
        void SetUpdatedBy(string user);
    }
    
    public partial class ExampleDBtable: EntityObject, Audit.IAuditable
    {
         //Normal EDMX stuff here..
         public static ExampleDBtable CreateExampleDBtable(int id, string code, string name, DateTime insertedOn, string insertedBy, DateTime updatedOn, string updatedBy)
           {
    
           }
           //Extension points.
        #region IAuditable Members
    
        public void SetInsertedOn(DateTime date)
        {
            this._InsertedOn = date;
        }
    
        public void SetInsertedBy(string user)
        {
            this._InsertedBy = user;
        }
    
        public void SetUpdatedOn(DateTime date)
        {
            this._UpdatedOn = date;
        }
    
        public void SetUpdatedBy(string user)
        {
            this._UpdatedBy = user;
        }
    
        #endregion
    
        }
    
    我还生成代码来处理审计信息的更新

       public ExampleDBObjectContext(string connectionString) : base(connectionString, "publicExampleDBObjectContext")
        {
            this.SavingChanges += new EventHandler(UpdateAuditInformation);
            this.OnContextCreated();
         }
    
       foreach (ObjectStateEntry entry in
                context.ObjectStateManager.GetObjectStateEntries(
                EntityState.Added | EntityState.Modified))
            {
                  //Start pseudo code..
                  if(entry.Entity is IAuditable){
                     IAuditable temp = entry.Entity as IAuditable;
                     temp.SetInsertedOn(DateTime.Now);
                     temp.SetInsertedBy(Env.GetUser());
                     ...
    
                  }
            }
    
    最后我实现了UpdateAuditInformation

       public ExampleDBObjectContext(string connectionString) : base(connectionString, "publicExampleDBObjectContext")
        {
            this.SavingChanges += new EventHandler(UpdateAuditInformation);
            this.OnContextCreated();
         }
    
       foreach (ObjectStateEntry entry in
                context.ObjectStateManager.GetObjectStateEntries(
                EntityState.Added | EntityState.Modified))
            {
                  //Start pseudo code..
                  if(entry.Entity is IAuditable){
                     IAuditable temp = entry.Entity as IAuditable;
                     temp.SetInsertedOn(DateTime.Now);
                     temp.SetInsertedBy(Env.GetUser());
                     ...
    
                  }
            }
    

    我选择不显示.tt文件,因为它在编辑器中看起来很糟糕。

    这并不是一个直接的答案,但我对LINQ to SQL做了类似的事情。查看我的博客帖子。它可能会给你一些想法。基本思想是扩展数据上下文,覆盖提交更改,并在那里执行审计工作。我的审核信息存储在另一个表中,我审核成功和失败,因此它使用单独的上下文,但您仍然可以从中获得一些想法。谢谢。我想用.tt文件做一些代码生成的东西,但我希望能有更简单的东西,今晚我会读一遍,然后给你回复。“迭代结果,如果需要的话设置属性。”吓到我了。。。你是说反思?不,我不是。检查每个修改的实体并查看其类型。如果你想审核它,那么设置
    entity.updateOn
    ,等等。除非它们都扩展了一些接口,否则你必须进行反射。我会选择一个接口。但不,这不是唯一的选择。您可以测试类型,然后也可以强制转换。我如何使所有实体扩展基类(将包含审核字段)?老实说,我不知道如何在edmx中映射这一点。我们无法找到正确的用户,我们从调用上下文中提取它,或者我们将使用触发器。您是否有机会再给我一点。。。我猜我的想法是用trace attributes>标记我的属性?是的。抱歉,没有看到您的问题。有可能定义一个程序集范围的跟踪attirubute。是的。上面没有样本,只有文字说明它可能会被用于。。