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

时间:2010-04-06 21:39:40

标签: c# algorithm entity-framework .net-3.5

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

 CreateDate
 CreateUser
 UpdateDate
 UpdateUser

目前,我们正在以编程方式更新审核信息。

前:

  if(changed){
        entity.UpdatedOn = DateTime.Now;
        entity.UpdatedBy = Environment.UserName;
        context.SaveChanges();
   }

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

有关我如何做到这一点的任何建议?我宁愿不做任何反思,所以使用文本模板并非不可能。

已经提出了一种解决方案来覆盖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
        }
   }

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

4 个答案:

答案 0 :(得分:1)

这是最终解决方案。

我基本上检查了我的模型是否存在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();
     }

最后我实现了UpdateAuditInformation

   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文件,因为它在编辑器中看起来很糟糕。

答案 1 :(得分:0)

是的,我认为你可以做这样的事情。一般的想法是

  1. 处理ObjectContext.SavingChanges
  2. 在该事件中,请致电ObjectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Modified)
  3. 根据需要迭代结果并设置属性。

答案 2 :(得分:0)

PostSharp。非常好的解决方案来完成这些任务。

答案 3 :(得分:0)

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