EF Extension Method Extravaganza Part I - ObjectStateEntry

So I’ve begun drinking the kool-aide. Extension methods are frighteningly addictive and don’t even get me started on LINQ to Objects. Now I can take a class which is missing some functionality that would make it just right for a particular problem and add it without having to change the underlying class, subclass, create a wrapper or some other painful process. To be honest this scares me a bit because it’s so addictive and so easy that I can tell now I’m going to be tempted to use it way too much. We’re going to need a lot more time before we can make informed judgment calls, but for now I’m just going to give in and “learn to love the bomb.”

In that vein, here’s the first installment in a series of posts with lots of little extension methods which seem to make my recent Entity Framework experiments easier to write. Over time, maybe some functionality similar to these will migrate their way into the product (particularly in some of those cases where I couldn’t do everything I wanted without a little reflection hackery), but even if they do not, there’s no reason why you can’t just copy some of them into your own project and enjoy. If you find them useful, let me know. Also, I use a lot of these in my promised (but taking ever so long to arrive) sample for transmitting graphs of entities along with change tracking information over a web service. So you can use these posts as an explanatory reference when you look over that code.

First we’ll look at a few extension methods that are pretty obvious and just tend to save me some typing:

public static EntityState GetEntityState(this ObjectContext context, EntityKey key)

{

    var entry = context.ObjectStateManager.GetObjectStateEntry(key);

    return entry.State;

}

public static string GetFullEntitySetName(this EntityKey key)

{

    return key.EntityContainerName + "." + key.EntitySetName;

}

public static IEntityWithKey GetEntityByKey(this ObjectContext context, EntityKey key)

{

    return (IEntityWithKey)context.ObjectStateManager.GetObjectStateEntry(key).Entity;

}

OK. Now that we’re warmed up, let’s dive into a few more interesting methods focused on working with ObjectStateEntries:

ObjectStateEntry.UsableValues()

One of the tricky aspects of working with entries in the ObjectStateManager is that there are two IExtendedDataRecord properties – one for original values and one for the current values – and depending on the “state” of the entry, it may be that you can access only one, only the other one, or both of them. Sometimes you don’t really care which record you get just as long as you can get your hands on one of them without the system throwing an exception (for example if you want to access the metadata describing the entry). So I created this method to retrieve a “usable” one without worrying about which.

public static IExtendedDataRecord UsableValues(this ObjectStateEntry entry)

{

    switch (entry.State)

    {

        case EntityState.Added:

        case EntityState.Detached:

        case EntityState.Unchanged:

        case EntityState.Modified:

            return (IExtendedDataRecord)entry.CurrentValues;

        case EntityState.Deleted:

            return (IExtendedDataRecord)entry.OriginalValues;

        default:

           throw new InvalidOperationException("This entity state should not exist.");

    }

}

ObjectStateEntry.EdmType()

The most basic kind of metadata you might want to retrieve for an ObjectStateEntry is the EdmType for the data the entry contains. Often this type will indicate that the entry is tracking an entity and allow you to retrieve the name of the entity type, its columns, etc. Alternatively, the entry might be tracking a relationship in which case the EdmType is really an AssociationType and will allow you to retrieve information, for instance about the ends of that kind of relationship…

public static EdmType EdmType(this ObjectStateEntry entry)

{

    return entry.UsableValues().DataRecordInfo.RecordType.EdmType;

}

AssociationType.IsManyToMany()

This method, of course, isn’t an extension to ObjectStateEntry, but it’s very convenient when combined with the above methods. If you have an ObjectStateEntry which is tracking a relationship, you can use this method to detect if that relationship has multiplicity *:*--important since these relationships often require a little extra handling.

public static bool IsManyToMany(this AssociationType associationType)

{

    foreach (RelationshipEndMember endMember in associationType.RelationshipEndMembers)

    {

        if (endMember.RelationshipMultiplicity != RelationshipMultiplicity.Many)

        {

            return false;

        }

    }

    return true;

}

Maybe that’s enough to chew on for one day. If you have the time and inclination, take these for a spin and let me know if you come up with anything interesting.

- Danny