C# 扩展基本类型并自动更新实体的审核信息
我有一个实体模型,每个表上都有审计信息(50多个表) 目前,我们正在按计划更新审计信息 例: 但我正在寻找一个更自动化的解决方案。在保存更改期间,如果创建/更新了实体,我希望在将这些字段发送到数据库进行存储之前自动更新这些字段 有没有关于我如何做到这一点的建议?我宁愿不做任何反射,所以使用文本模板也不是不可能的 有人提出了一种解决方案来覆盖SaveChanges并在那里执行,但为了实现这一点,我要么使用反射(我不想在其中执行),要么派生一个基类。假设我沿着这条路走下去,我将如何实现这一点 比如说C# 扩展基本类型并自动更新实体的审核信息,c#,algorithm,entity-framework,.net-3.5,C#,Algorithm,Entity Framework,.net 3.5,我有一个实体模型,每个表上都有审计信息(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
}
看。这类任务的解决方案非常好。通过数据库触发器“标记”更新的行不是更简单吗?数据库中提供的信息是否不够充分?(数据库用户与操作系统用户)这是最终的解决方案 我基本上检查我的模型是否存在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。是的。上面没有样本,只有文字说明它可能会被用于。。