Search code examples
c#entity-frameworkef-database-first

How to get the the Schama.TableName in EF 6 database-first?


I'm using EF 6 database-first.. I use this method to get the name of the table:

private static string GetTableName(ObjectContext context, Type entityType)
        {
            string entityTypeName = entityType.Name;

            EntityContainer container = context.MetadataWorkspace.GetEntityContainer(context.DefaultContainerName, DataSpace.CSpace);
            string tableName = (from meta in container.BaseEntitySets
                                where meta.ElementType.Name == entityTypeName
                                select meta.Name).First();
            return tableName;
        }

but it only returns the table name, I have 5 schemas in the database, every schema corresponds to a separate DbContext, so it might have identical names with different schema. So I need to return the full name of the table


Solution

  • Basically you need Table and Schema properties of the EntitySet class. Unfortunately they are correctly populated only for the storage model, so in order to find it, you'll need to go through several model mappings.

    Here is a sample method based on (in fact part of) the excellent post EF6.1 Get Mapping Between Properties and Columns` by Rowan Miller:

    static EntitySet GetStorageEntitySet(ObjectContext objectContext, Type clrEntityType)
    { 
        var metadata = objectContext.MetadataWorkspace;
    
        // Get the part of the model that contains info about the actual CLR types
        var objectItemCollection = ((ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace));
    
        // Get the entity type from the model that maps to the CLR type
        var entityType = metadata
                .GetItems<EntityType>(DataSpace.OSpace)
                      .Single(e => objectItemCollection.GetClrType(e) == clrEntityType);
    
        // Get the entity set that uses this entity type
        var entitySet = metadata
            .GetItems<EntityContainer>(DataSpace.CSpace)
                  .Single()
                  .EntitySets
                  .Single(s => s.ElementType.Name == entityType.Name);
    
        // Find the mapping between conceptual and storage model for this entity set
        var mapping = metadata.GetItems<EntityContainerMapping>(DataSpace.CSSpace)
            .Single()
            .EntitySetMappings
            .Single(s => s.EntitySet == entitySet);
    
        // Find the storage entity set (table) that the entity is mapped
        return mapping
            .EntityTypeMappings.Single()
            .Fragments.Single()
            .StoreEntitySet;
    }
    

    Sample usage in your case:

    private static string GetTableName(ObjectContext context, Type entityType)
    {
        var entitySet = GetStorageEntitySet(context, entityType);
        return entitySet.Schema + "." + entitySet.Table;
    }
    

    Update: It turns out that there are differences between Code First and Database First in regard to EntitySet Table and Name properties, so to get the table name generically I would suggest using:

    var tableName = entitySet.Table ?? entitySet.Name;