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

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

CreateDate CreateUser UpdateDate UpdateUser 

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

例如:

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

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

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

已经提出了一种解决方案来覆盖SaveChanges并在那里进行,但是为了实现这一点,我要么必须使用reflection(我不想做)或者派生基类。 假设我沿着这条路走下去,我将如何实现这一目标?

例如

 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个属性。 如果实体包含

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. 处理ObjectContext.SavingChanges 。
  2. 在那种情况下,调用ObjectContext.ObjectStateManager.GetObjectStateEntries (EntityState.Modified)
  3. 如果需要,迭代结果并设置属性。

看看PostSharp 。 这样的任务非常好的解决方案。

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