Monday, November 29, 2010

Entity Framework 4 – Encapsulate BaseEntity property change logic

Overriding the SavingChanges event on the ObjectContext allows us to create functions that can make changes to the BaseEntity exposed properties for our model. For example in the previous post, we had all our entities inherited from a BaseEntity which exposed our change tracking properties. To update or add values to these properties which is common to all entities we can use the SavingChanges event on the ObjectContext. For e.g In my model, I have implemented the SavingChanges event as.
public ShoppingCartContext() : base("name=ShoppingCartModelContainer", "ShoppingCartModelContainer")
{
    this.SavingChanges += new EventHandler((sender, e) =>
    {
        UpdateBaseEntityPropertiesForNewlyAddedEntities(e);
        UpdateBaseEntityPropertiesForModifiedEntities(e);               
    });
}

private void UpdateBaseEntityPropertiesForNewlyAddedEntities(EventArgs e)
{
    var addedEntities = this.ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Added)
        .Where(entity => entity.Entity is BaseEntity)
        .Select(entity => entity.Entity as BaseEntity);

    addedEntities.ToList().ForEach(baseEntity =>
        {
            baseEntity.Id = baseEntity.Id == Guid.Empty ? Guid.NewGuid() : baseEntity.Id;
            baseEntity.CreatedDate = baseEntity.ChangedDate = DateTime.Now;
        });
}

private void UpdateBaseEntityPropertiesForModifiedEntities(EventArgs e)
{
    var modifiedEntities = this.ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Modified)
        .Where(entity => entity.Entity is BaseEntity)
        .Select(entity => entity.Entity as BaseEntity);

    modifiedEntities.ToList().ForEach(baseEntity => baseEntity.ChangedDate = DateTime.Now);
}

Test cases:
[TestMethod]
public void override_method_for_savingChanges_should_update_the_baseEntity_properties()
{
    Guid productId = Guid.NewGuid();
    var product = new Product
    {
        Id = productId,
        ProductName = "New Product",
        UnitPrice = 56.87M
    };

    using (var context = new ShoppingCartContext())
    {
        context.Products.AddObject(product);
        context.SaveChanges();
    }

    using (var context = new ShoppingCartContext())
    {
        var insertedProduct = (from p in context.Products
                                where p.Id == productId
                                select p).SingleOrDefault();

        Assert.IsTrue(insertedProduct.CreatedDate.Date == DateTime.Today.Date);
    }
}

No comments: