我有一个实体模型,每个表都有审计信息(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
}
}
但我不确定如何生成扩展接口的代码。
答案 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)
是的,我认为你可以做这样的事情。一般的想法是
答案 2 :(得分:0)
请PostSharp。非常好的解决方案来完成这些任务。
答案 3 :(得分:0)
通过数据库触发器“标记”更新的行是不是更简单?数据库中提供的信息不够充分吗? (数据库用户与操作系统用户)