Entity framework 实体框架-审计活动
我的数据库在每个表上都有一个“LastModifiedUser”列,我打算在其中从进行更改的应用程序收集登录用户。我不是说数据库用户,所以本质上这只是每个实体上的一个字符串。我想找到一种为每个实体设置默认值的方法,以便其他开发人员在实例化实体时不必记住分配它 这样的事情就会发生:Entity framework 实体框架-审计活动,entity-framework,entity,auditing,Entity Framework,Entity,Auditing,我的数据库在每个表上都有一个“LastModifiedUser”列,我打算在其中从进行更改的应用程序收集登录用户。我不是说数据库用户,所以本质上这只是每个实体上的一个字符串。我想找到一种为每个实体设置默认值的方法,以便其他开发人员在实例化实体时不必记住分配它 这样的事情就会发生: using (EntityContext ctx = new EntityContext()) { MyEntity foo = new MyEntity(); // Trying to avoid
using (EntityContext ctx = new EntityContext())
{
MyEntity foo = new MyEntity();
// Trying to avoid having the following line every time
// a new entity is created/added.
foo.LastModifiedUser = Lookupuser();
ctx.Foos.Addobject(foo);
ctx.SaveChanges();
}
在EF4.0中,有一种通过利用
首先,需要为ObjectContext创建一个分部类并订阅 。订阅此事件的最佳位置是在OnContextCreated方法内。此方法由上下文对象的构造函数调用,构造函数重载是没有实现的部分方法:
partial void OnContextCreated() {
this.SavingChanges += Context_SavingChanges;
}
现在,将执行此任务的实际代码:
void Context_SavingChanges(object sender, EventArgs e) {
IEnumerable<ObjectStateEntry> objectStateEntries =
from ose
in this.ObjectStateManager.GetObjectStateEntries(EntityState.Added
| EntityState.Modified)
where ose.Entity != null
select ose;
foreach (ObjectStateEntry entry in objectStateEntries) {
ReadOnlyCollection<FieldMetadata> fieldsMetaData = entry.CurrentValues
.DataRecordInfo.FieldMetadata;
FieldMetadata modifiedField = fieldsMetaData
.Where(f => f.FieldType.Name == "LastModifiedUser").FirstOrDefault();
if (modifiedField.FieldType != null) {
string fieldTypeName = modifiedField.FieldType.TypeUsage.EdmType.Name;
if (fieldTypeName == PrimitiveTypeKind.String.ToString()) {
entry.CurrentValues.SetString(modifiedField.Ordinal, Lookupuser());
}
}
}
}
这将导致在创建上下文时调用OnContextCreated()。
现在,如果您将POCO放在服务边界之后,那么这意味着ModifiedUserName必须与来自WCF服务使用者的其余数据一起提供。你可以公开这个 LastModifiedUser属性更新,或者如果它存储在另一个属性中,并且您希望从该属性更新LastModifiedUser,则可以修改第二个代码,如下所示:
foreach (ObjectStateEntry entry in objectStateEntries) {
ReadOnlyCollection fieldsMetaData = entry.CurrentValues
.DataRecordInfo.FieldMetadata;
FieldMetadata sourceField = fieldsMetaData
.Where(f => f.FieldType.Name == "YourPropertyName").FirstOrDefault();
FieldMetadata modifiedField = fieldsMetaData
.Where(f => f.FieldType.Name == "LastModifiedUser").FirstOrDefault();
if (modifiedField.FieldType != null) {
string fieldTypeName = modifiedField.FieldType.TypeUsage.EdmType.Name;
if (fieldTypeName == PrimitiveTypeKind.String.ToString()) {
entry.CurrentValues.SetString(modifiedField.Ordinal,
entry.CurrentValues[sourceField.Ordinal].ToString());
}
}
}
希望这能有所帮助。现在有一个nuget软件包:
Github:谢谢你的回答。我以前研究过这种模式,但无法启动onContextCreated事件。没问题。正如我所说,OnContextCreated不是一个事件,它只是一个没有实现的部分方法,由上下文对象的构造函数和构造函数重载调用。您所需要做的就是为您的上下文创建一个分部类,并将我的第一个代码片段放入其中。请这样做,让我知道它是如何为您工作的,如果它仍然不工作,我们将使它工作!事实上,我的想法是错误的,因此描述是错误的。让我完善我的问题。。。我们使用self-trackign实体,它们通过WCF服务提供给前端。当它们返回时,我们重新连接到上下文并保存。如果在拥有客户机时对其进行了修改,则lastModifiedUser需要反映这一点。服务器没有权限知道当前用户是谁,因此它不能负责设置用户。我假设在理论上我想在实体级别做一些类似于oncreated event/partial方法的事情?好的,现在我明白你的意思了。我更新答案以解决POCO情况。请试一试,上面的代码有点错误。测试
if(modifiedField.FieldType!=null)
应替换为if(modifiedField!=null)
foreach (ObjectStateEntry entry in objectStateEntries) {
ReadOnlyCollection fieldsMetaData = entry.CurrentValues
.DataRecordInfo.FieldMetadata;
FieldMetadata sourceField = fieldsMetaData
.Where(f => f.FieldType.Name == "YourPropertyName").FirstOrDefault();
FieldMetadata modifiedField = fieldsMetaData
.Where(f => f.FieldType.Name == "LastModifiedUser").FirstOrDefault();
if (modifiedField.FieldType != null) {
string fieldTypeName = modifiedField.FieldType.TypeUsage.EdmType.Name;
if (fieldTypeName == PrimitiveTypeKind.String.ToString()) {
entry.CurrentValues.SetString(modifiedField.Ordinal,
entry.CurrentValues[sourceField.Ordinal].ToString());
}
}
}