开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜