Monday, September 08, 2008

Tommy on the Train and in the Snow!

DSC03595DSC03593DSC03591DSC03587DSC03597DSC03590DSC03587DSC03586DSC03585DSC03582DSC03581DSC03579DSC03576DSC03574DSC03573DSC03561DSC03558DSC03565DSC03569

Monday, September 08, 2008 11:40:19 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Saturday, August 16, 2008

Entity Framework - Key Extension Methods

We created the following extension methods for entity framework to avoid code bloat in consuming applications when working with these key types. I hope you find them useful if you are working with the Entity Framework.

 

EntityObject

/// <summary>
/// Extension methods for EntityObject
/// </summary>
public static class EntityObjectExtensions
{

    /// <summary>
    /// Gets the original value for a modified entity object's property
    /// </summary>
    /// <returns>the value before the property was modified</returns>
    public static T GetOriginalValue<T>(this EntityObject entityObject, string propertyName)
    {
        if (entityObject == null)
            return default(T);
        if (entityObject.EntityState == EntityState.Modified)
        {
            ObjectContext context = [YOUR OBJECT CONTEXT]
            ObjectStateEntry stateEntry = null;
            context.ObjectStateManager.TryGetObjectStateEntry(entityObject, out stateEntry);

            if (stateEntry != null)
                return (T)stateEntry.OriginalValues.GetValue(stateEntry.OriginalValues.GetOrdinal(propertyName));

        }

        // return the value of the property
        return (T)entityObject.GetType().GetProperty(propertyName).GetValue(entityObject, null);
    }

EntityCollection<T>

/// <summary>
   /// Extension methods for EntityCollection
   /// </summary>
   public static class EntityCollectionExtensions
   {
       /// <summary>
       /// Loads the entity collection if it hasn't already been loaded
       /// </summary>
       /// <typeparam name="T">Type of entity collection</typeparam>
       /// <param name="entityCollection">Entity collection to potentially load entities into</param>
       /// <param name="entitySource">The source entity which has the entity collection relationship (modified or unchanged only)</param>
       public static void EnsureLoaded<T>(this EntityCollection<T> entityCollection, EntityObject entitySource) where T : class, IEntityWithRelationships
       {
           if (entitySource != null && entityCollection != null && !entityCollection.IsLoaded )
           {
               if (entitySource.EntityState == System.Data.EntityState.Modified || entitySource.EntityState == System.Data.EntityState.Unchanged)
               {
                   entityCollection.Load();
               }
           }
       }

       /// <summary>
       /// Returns the collection as a queryable type
       /// </summary>
       /// <typeparam name="T">Type of entity collection</typeparam>
       /// <param name="entityCollection">Entity collection to return as a queryable object</param>
       /// <param name="ensureLoaded">Flag to determine if to load the collection if it has not been done so already</param>
       /// <returns>Queryable object for the in memory collection</returns>
       public static IQueryable<T> AsQueryable<T>(this EntityCollection<T> entityCollection, bool ensureLoaded, EntityObject entitySource) where T : class, IEntityWithRelationships
       {
           if (ensureLoaded)
               EnsureLoaded(entityCollection, entitySource);
           return entityCollection.AsQueryable();
       }

 

EntityReference<T>

 

/// <summary>
   /// Extension methods for EntityReference
   /// </summary>
   public static class EntityReferenceExtensions
   {

       /// <summary>
       /// Loads the entity reference or its value if it hasn't already been loaded.
       /// </summary>
       /// <typeparam name="T">Type of entity reference</typeparam>
       /// <param name="entitySource">The source entity which has the entity reference relationship (added, modified or unchanged only)</param>
       public static void EnsureLoaded<T>(this EntityReference<T> entityReference, EntityObject entitySource) where T : class, IEntityWithRelationships
       {
           if (entitySource != null && entityReference != null && !entityReference.IsLoaded && entityReference.EntityKey != null)
           {
               if (entitySource.EntityState == System.Data.EntityState.Added) // add the value directly as load will throw
               {
                   if (entityReference.Value == null)
                       entityReference.Value = LoadByKey<T>(entityReference.EntityKey);
               }
               else if (entitySource.EntityState == System.Data.EntityState.Modified || entitySource.EntityState == System.Data.EntityState.Unchanged)
               {
                   entityReference.Load();
               }
           }
       }

privateT LoadByKey<T>(object entityKey)
{
    if (entityKey == null)
        throw new ArgumentNullException("Supplied entity key is null, unable to load entity", "entityKey");
    // make sure the object is loaded in the object context
    ObjectContext objectContext = [YOUR OBJECT CONTEXT];
    EntityKey key = (EntityKey)entityKey;
    ObjectStateEntry entry;
    if (!objectContext.ObjectStateManager.TryGetObjectStateEntry(entityKey, out entry) || entry.Entity == null)
    {
        return (T)objectContext.GetObjectByKey(key);
    }
    return (T)entry.Entity;
}

       /// <summary>
       /// Whether or not the entity reference has an entity key with a value present
       /// </summary>
       public static bool HasEntityKeyFirstValue<T>(this EntityReference<T> entityReference) where T : class, IEntityWithRelationships
       {
           return entityReference != null && entityReference.EntityKey.HasFirstValue<int>();
       }

       /// <summary>
       /// Get entity key with a value present
       /// </summary>
       public static int GetEntityKeyFirstValue<T>(this EntityReference<T> entityReference) where T : class, IEntityWithRelationships
       {
           if (entityReference != null)
               return entityReference.EntityKey.GetFirstValue<int>();
           return 0;
       }

 

EntityKey

 

/// <summary>
   /// Extension methods for EntityKey
   /// </summary>
   public static class EntityKeyExtensions
   {

       /// <summary>
       /// Gets the first entity key value
       /// </summary>
       /// <returns>the first entity key value</returns>
       public static T GetFirstValue<T>(this EntityKey entityKey)
       {
           if (entityKey != null && entityKey.EntityKeyValues != null && entityKey.EntityKeyValues.Length > 0)
               return (T)entityKey.EntityKeyValues.First().Value;
           return default(T);
       }

       /// <summary>
       /// Sets the first entity key value
       /// </summary>
       public static void SetFirstValue<T>(this EntityKey entityKey, T value)
       {
           if (entityKey != null && entityKey.EntityKeyValues != null && entityKey.EntityKeyValues.Length > 0)
               entityKey.EntityKeyValues.First().Value = value;
           return;
       }

       /// <summary>
       /// Whether or not the entity key has a first value
       /// </summary>
       public static bool HasFirstValue<T>(this EntityKey entityKey)
       {
           var firstValue = GetFirstValue<T>(entityKey);
           var defaultValue = default(T);
           return (!firstValue.Equals(defaultValue));
       }

Saturday, August 16, 2008 3:26:05 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, August 15, 2008

Tommy has a new bed

Friday, August 15, 2008 12:47:57 AM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [1]  |  Trackback

Tommy Goes on Holiday

Friday, August 15, 2008 12:37:04 AM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Saturday, August 09, 2008

Tamaki Drive Sunset

All i can say is roll on spring....Probably my favouritest part of auckland is the tamaki drive stretch out east. And sometimes you get blindingly beautiful sunsets back across the city view.

08042008231

Saturday, August 09, 2008 10:16:26 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Tuesday, August 05, 2008

Tommy gets a new bed

Tommy is officially a big boy now he has his own bed. He even wants to go to bed early at the moment, not sure how long that will last though!

 

02082008524

Tuesday, August 05, 2008 1:34:13 AM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, July 20, 2008

Christchurch Weekend

Sorry lucy, no pictures of tommy as yet, here's some snaps of our weekend down at christchurch/hamner springs. Will some trees do instead??

DSC03537DSC03538DSC03539DSC03541DSC03542DSC03544DSC03546DSC03550DSC03557

Sunday, July 20, 2008 4:24:11 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, July 13, 2008

Sorry Lucy, more pics coming soon

Lucy just reminded me that i must post mroe family pics soon. She however requesed pics of tommy explicitly even though i'm undoubtedly more handsome, strange...

Here's one of us in London to keep you going lucy.

DSC03511

Sunday, July 13, 2008 8:44:48 PM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, July 04, 2008

Entity Framework Lazy Loading - A quick alternative with extension methods

I saw the following code on a customer object which made me think about affording a better way to query domain relationships without the extra methods, extension methods come to the rescue!

I realise transparent lazy loading a la Nhibernate is another option, but i think that this way keeps the spirit of explicitly loading from the database, but reduces the amount of code clutter on the client side so you are not forever checking whether a relationship is loaded or not, you simply request an IQueryable from the EntityCollection<T>.

        /// <summary>
        /// Finds a customer account with the specified ID
        /// </summary>
        /// <param name="customerAccountID">ID of the customer account to find</param>
        /// <returns>Customer account with the specified ID</returns>
        public CustomerAccount FindAccount(int customerAccountID)
        {
            if(!this.CustomerAccounts.IsLoaded)
            {
                this.CustomerAccounts.Load();
            }

            var query =
                from ca in this.CustomerAccounts
                where ca.CustomerAccountID == customerAccountID
                select ca;

            return query.FirstOrDefault();
        }

I added a static class with the extension methods for the EntityCollection type as follows:

public static class EntityCollectionExtensions
    {
        public static EntityCollection<T> EnsureLoaded<T>(this EntityCollection<T> entityCollection) where T : class, IEntityWithRelationships
        {
            if (!entityCollection.IsLoaded)
                entityCollection.Load();
            return entityCollection;
        }

        public static IQueryable<T> AsQueryable<T>(this EntityCollection<T> entityCollection, bool ensureLoaded) where T : class, IEntityWithRelationships
        {
            if (ensureLoaded)
                entityCollection = EnsureLoaded<T>(entityCollection);
            return entityCollection.AsQueryable();        }
    }

This allows you to do the following, which will only go to the database if the relationship is not loaded.

            var query =
                from ca in this.CustomerAccounts.AsQueryable(true) // ensure the relationship is loaded and return a queryable on it
                where ca.CustomerAccountID == customerAccountID
                select ca;
    return query.FirstOrDefault();

Friday, July 04, 2008 8:44:57 AM (New Zealand Standard Time, UTC+12:00)  #    Disclaimer  |  Comments [0]  |  Trackback