8

I'm using the Entity Framework 4.1 with Code First approach. I'm able to get the storage model types and column names of my entities:

var items = context.ObjectContext.MetadataWorkspace.GetItems<EntityType>(DataSpace.SSpace);

foreach (var i in items)
{
    Console.WriteLine("Table Name: {0}", i.Name);

    Console.WriteLine("Keys:");
    foreach (var key in i.KeyMembers)
        Console.WriteLine("\t{0} ({1})", key.Name, key.TypeUsage.EdmType.FullName);

    Console.WriteLine("Members:");
    foreach (var member in i.Members)
        Console.WriteLine("\t{0} ({1})", member.Name, member.TypeUsage.EdmType.FullName);
}

What I need is to get the real table name the entity is mapped to. There are different ways to specify that (by using Fluent-API .ToTable(), DataAnnotation [TableAttribute]).

Is there any common way to achieve this information?

0xbadf00d
  • 17,405
  • 15
  • 67
  • 107

3 Answers3

11

EF 6.1, code-first:

public static string GetTableName<T>(this DbContext context) where T : class
{
    ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext;
    return objectContext.GetTableName(typeof(T));
}

public static string GetTableName(this DbContext context, Type t)
{
    ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext;
    return objectContext.GetTableName(t);
}

private static readonly Dictionary<Type,string> TableNames = new Dictionary<Type, string>();

public static string GetTableName(this ObjectContext context, Type t)
{
    string result;

    if (!TableNames.TryGetValue(t, out result))
    {
        lock (TableNames)
        {
            if (!TableNames.TryGetValue(t, out result))
            {

                string entityName = t.Name;

                ReadOnlyCollection<EntityContainerMapping> storageMetadata = context.MetadataWorkspace.GetItems<EntityContainerMapping>(DataSpace.CSSpace);

                foreach (EntityContainerMapping ecm in storageMetadata)
                {
                    EntitySet entitySet;
                    if (ecm.StoreEntityContainer.TryGetEntitySetByName(entityName, true, out entitySet))
                    {
                        result = entitySet.Schema + "." + entitySet.Table;//TODO: brackets
                        break;
                    }
                }

                TableNames.Add(t,result);
            }
        }
    }

    return result;
}
Motlicek Petr
  • 767
  • 9
  • 10
  • Please consider including some information about your answer, rather than simply posting code. We try to provide not just 'fixes', but help people learn. You should explain what was wrong in the original code, what you did differently, and why your change(s) worked. – Andrew Barber Dec 01 '14 at 02:39
  • 4
    I thought starting with "EF 6.1, code-first" is quite OK.... – Motlicek Petr Apr 16 '15 at 10:51
  • I don't know why, it doesn't work (for me) using db-first. Check my answer here. http://stackoverflow.com/a/32871720/382515 – Ivan Ferrer Villa Sep 30 '15 at 17:05
  • This does not work for SQL Server Compact. Schema, e.g. "dbo" is added to the name and that is wrong. – Motlicek Petr Oct 20 '16 at 10:30
10

The Easiest way I have found to get table names is the following:

var tables = Context.MetadataWorkspace.GetItems(System.Data.Metadata.Edm.DataSpace.CSpace)
                .Where(x => (x.MetadataProperties.Contains("NamespaceName") ? String.Compare(x.MetadataProperties["NamespaceName"].Value.ToString(), "Model", true) == 0 : false)
                && !x.MetadataProperties.Contains("IsForeignKey")
                && x.MetadataProperties.Contains("KeyMembers"));

That will get you the table entities.

Then you can do the following to extract the name:

            foreach (var item in tables)
            {
                EntityType itemType = (EntityType)item;
                String TableName = itemType.Name;
            }

Note if your pluralizing the context you will need to undo that.

Chris Lucian
  • 1,013
  • 6
  • 15
1

There is an other way you can get the EDM Table Name

  public static string GetTableName<T>(this ObjectContext context) where T : EntityObject
    {
        var entities= context.MetadataWorkspace.GetItems(System.Data.Metadata.Edm.DataSpace.CSpace).Where(b => b.BuiltInTypeKind == BuiltInTypeKind.EntityType);

        foreach (System.Data.Metadata.Edm.EntityType item in entities)
        {
            if(item.FullName==typeof(T).FullName)
                return item.Name;
        }

        return String.Empty;
    }
IT Fresher
  • 155
  • 8