static void

EF Code First - is entity transient?

Published Tuesday 20 March 2012

When the Code First project get a detached entity from the UI, it may need to check if it is a new (transient) entity - which can be added to the DbSet - or an existing entity that has been modified. You can then implement an AddOrUpdate method.

To do that, it needs to know what the primary key of the entity is, and read the value.

The easiest way to do is generically is for all entities to have a standard interface or abstract base.
var id = ((IEntity) entity).Id;
if (id == default(int))
{
    //add
}
else
{
    //update
}
If you use the [Key] attribute you can also use that to discover the primary key of the entity, whatever the type.

Finally,  you can use EF's internal metadata.
public static bool IsTransient<T>(DbContext context, T entity)
    where T : class
{
    //find the primary key
    var objectContext = ((IObjectContextAdapter)context).ObjectContext;
    //this will error if it's not a mapped entity
    var objectSet = objectContext.CreateObjectSet<T>();
    var elementType = objectSet.EntitySet.ElementType;
    var pk = elementType.KeyMembers.First();
    //look it up on the entity
    var propertyInfo = typeof(T).GetProperty(pk.Name);
    var propertyType = propertyInfo.PropertyType;
    //what's the default value for the type?
    var transientValue = propertyType.IsValueType ? Activator.CreateInstance(propertyType) : null;
    //is the pk the same as the default value (int == 0, string == null ...)
    return propertyInfo.GetValue(entity, null) == transientValue;
}

Previously: EF Code First - Generically setting entity references to unchanged status (19 Mar 2012)