通过利用ObjectStateManager
在 EF 4.0 中有一个完美的方法来完成此操作。
首先,您需要为 ObjectContext 创建一个分部类并订阅
ObjectContext.SavingChanges 事件。订阅此事件的最佳位置是在 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());
}
}
}
}
代码说明:
此代码查找任何具有LastModifiedUser属性的已添加或已修改条目,然后使用来自您的自定义Lookupuser()方法的值更新该属性。
在 foreach 块中,查询基本上深入到每个条目的CurrentValues。然后,使用Where方法,它查看该条目的每个FieldMetaData项的名称,只选择那些Name为LastModifiedUser的项。接下来,if 语句验证LastModifiedUser属性是否为String
场地; 然后它更新字段的值。
连接此方法的另一种方法(而不是订阅SavingChanges事件)是覆盖ObjectContext.SaveChanges 方法。
顺便说一句,上面的代码属于Julie Lerman,来自她的Programming Entity Framework书。
自我跟踪 POCO 实现的编辑:
如果您有自我跟踪 POCO,那么我要做的是首先更改 T4 模板以调用 OnContextCreated() 方法。如果您查看您的 ObjectContext.tt 文件,则有一个Initialize()由所有构造函数调用的方法,因此是调用我们的 OnContextCreated() 方法的一个很好的候选者,所以我们需要做的就是像这样更改 ObjectContext.tt 文件:
private void Initialize()
{
// Creating proxies requires the use of the ProxyDataContractResolver and
// may allow lazy loading which can expand the loaded graph during serialization.
ContextOptions.ProxyCreationEnabled = false;
ObjectMaterialized += new ObjectMaterializedEventHandler(HandleObjectMaterialized);
// We call our custom method here:
OnContextCreated();
}
这将导致我们的 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());
}
}
}
希望这可以帮助。