ef4 record stamping, inserted_at, inserted_by
is there any way of going through all the new/modified entities and setting their, inserted_at, updated_at fields?
With ObjectStateManager I can get a list of those entities but could not find a way of setting the entity property values.
foreach (var item in db.ObjectStateManager.GetObjectStateEntries(EntityState.Added))
{
System.Data.Objects.DataClasses.EntityObject entity = (System.Data.Objects.DataClasses.EntityObject)(item.Entity);
// now how can I set its .inserted_at to DateTime.Now
}
here is my current solution
public interface IUpdateTrack
{
DateTime? updated_at { get; set; }
Guid? updated_by { get; set; }
}
public interface IInsertTrack
{
DateTime? inserted_at { get; set; }
Guid? inserted_by { get; set; }
}
implement the interface in the partial class
public partial class crm_customer : BaseDB.IInsertTrack, BaseDB.IUpdateTrack
in the repository class
public void Save()
{
foreach (var item in db.ObjectStateManager.GetObjectStateEntries(EntityState.Added))
{
System.Data.Objects.DataClasses.EntityObje开发者_如何学JAVAct entity = (System.Data.Objects.DataClasses.EntityObject)(item.Entity);
if (item.Entity is BaseDB.IInsertTrack)
{
IInsertTrack insert_track = (IInsertTrack)(item.Entity);
insert_track.inserted_at = DateTime.Now;
insert_track.inserted_by = BaseDB.SessionContext.Current.ActiveUser.UserUid;
}
}
foreach (var item in db.ObjectStateManager.GetObjectStateEntries(EntityState.Modified))
{
if (item.Entity is BaseDB.IUpdateTrack)
{
IUpdateTrack update_track = (IUpdateTrack)(item.Entity);
update_track.updated_at = DateTime.Now;
update_track.updated_by = BaseDB.SessionContext.Current.ActiveUser.UserUid;
}
}
I would like a solution that does not require implementing the interface for each class in the model, its error prone, you might forget to implement this interfaces for some classes. I am using EF4 using database-first approach.
Yes, there is a perfect way to accomplish this in Entity Framework 4.0, Thanks to Julia Lerman for pointing out this nice trick.
using System.Data.Common;
using System.Data.Metadata.Edm;
...
var entries = from e in db.ObjectStateManager.GetObjectStateEntries(
EntityState.Added | EntityState.Modified)
where e.Entity != null
select e;
foreach (var entry in entries) {
var fieldMetaData = entry.CurrentValues.DataRecordInfo.FieldMetadata;
FieldMetadata updatedAtField = fieldMetaData
.Where(f => f.FieldType.Name == "updated_at").FirstOrDefault();
if (updatedAtField.FieldType != null) {
string fieldTypeName = updatedAtField.FieldType.TypeUsage.EdmType.Name;
if (fieldTypeName == PrimitiveTypeKind.DateTime.ToString()) {
entry.CurrentValues.SetDateTime(updatedAtField.Ordinal,
DateTime.Now);
}
}
}
You can then call this code from within the SavingChanges event to be sure that any updated_at field is automatically updated.
By the way, the System.Data.Metadata.Edm namespace gives you access to the PrimitiveTypeKind class.
精彩评论