As I said in a comment, your solution works by virtue of a code-first store model returning the CLR type names from EntityType
. A database-first store model, however, returns the store names. These names do not necessarily match the CLR type names.
To make this method independent of EF's store model, we need to access the store-CLR mapping space (CSSpace
) and find the EntitySet
(by CLR name) and match its KeyMembers
with the columns in the store model (Property.Column
), because these columns contain the right value of IsStoreGeneratedIdentity
. (CLR properties also have this property, but it's always false).
So this is what we get (as a method encapsulated in a DbContext
subtype):
public bool IsStoreGeneratedIdentity<TEntity>()
{
var entityContainerMappings = (this as IObjectContextAdapter).ObjectContext
.MetadataWorkspace.GetItems(DataSpace.CSSpace)
.OfType<EntityContainerMapping>();
var entityTypeMappings = entityContainerMappings
.SelectMany(m => m.EntitySetMappings
.Where(esm => esm.EntitySet.ElementType.Name == typeof(TEntity).Name))
.SelectMany(esm => esm.EntityTypeMappings).ToArray();
var keyMappings = (from km in entityTypeMappings.SelectMany(etm => etm.EntityType.KeyMembers)
join pm in entityTypeMappings.SelectMany(etm => etm.Fragments)
.SelectMany(mf => mf.PropertyMappings)
.OfType<ScalarPropertyMapping>()
on km.Name equals pm.Property.Name
select pm
);
return keyMappings.Any(pm => pm.Column.IsStoreGeneratedIdentity);
}