Get Database Table Name from Entity Framework Meta

2019-01-02 15:28发布

I'm trying to figure out a way to get the underlying SQL table name for a given entity type. I've experimented around with the MetadataWorkspace queries and while I can get lots of information from the object or the storage space, I can't seem to figure out how to map between the two.

So say I have a type in the object model called Lookup - how do I find the tablename (wws_lookups) in the database?

I can query all the EntityType objects for CSpace and SSpace and I can see both listed correctly but I can't figure out how to get SSpace from CSpace.

Is there any way to do this?

22条回答
姐姐魅力值爆表
2楼-- · 2019-01-02 16:14

You can try MappingAPI extension: https://efmappingapi.codeplex.com/

It is really easy to use

context.Db<YourEntityType>().TableName
若你有天会懂
3楼-- · 2019-01-02 16:15

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))
                        {
                            if (String.IsNullOrEmpty(entitySet.Schema))
                            {
                                result = entitySet.Table;
                                break;
                            }


                            //we must recognize if we are under SQL Server Compact version, which does not support multiple schemas
                            //SQL server compact does not support schemas, entity framework sets entitySet.Schema set to "dbo", anyway
                            //the System.Data.Entity.Infrastructure.TableExistenceChecker.GetTableName() returns only table name
                            //schema is (not) added by the overrides of the method AnyModelTableExistsInDatabase
                            //the SqlCeTableExistenceChecker has the knowledge that there is no metadata schema needed
                            //the SqlTableExistenceChecker has the knowledge that there is metadata with schema, which should be added to the table names

                            var entityConnection = (System.Data.Entity.Core.EntityClient.EntityConnection) context.Connection;

                            DbConnection storeConnection = entityConnection.StoreConnection;

                            if (storeConnection != null && "SqlCeConnection".Equals(storeConnection.GetType().Name, StringComparison.OrdinalIgnoreCase))
                            {
                                result = entitySet.Table;
                                break;
                            }

                            result = entitySet.Schema  + "." + entitySet.Table;
                            break;
                        }
                    }

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

        return result;
    }
查看更多
残风、尘缘若梦
4楼-- · 2019-01-02 16:16

If you are using the T4 template for POCO classes you can get it by altering the T4 Template. See snippet:

<#  
////////////////////////////////////////////////////////////////////////////////
region.Begin("Custom Properties");

string xPath = "//*[@TypeName='" + entity.FullName + "']";
XmlDocument doc = new XmlDocument();
doc.Load(inputFile);

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("edmx", "http://schemas.microsoft.com/ado/2008/10/edmx");

XmlNode item;
XmlElement root = doc.DocumentElement;
item = root.SelectSingleNode(xPath);

#>
    //<#= xPath #>
    //<#= entity.FullName #>
    //<#= (item == null).ToString() #>

<# if (item != null) #>
// Table Name from database
public string TableName { get { return "<#= item.ChildNodes[0].Attributes["StoreEntitySet"].Value #>"; } }
<#

region.End();

////////////////////////////////////////////////////////////////////////////////
查看更多
弹指情弦暗扣
5楼-- · 2019-01-02 16:16

Alex is right - this is a sad limitation in the Metadata API. I have to just load the MSL as an XML document and do lookups of S-space entities as I process my C-space model.

登录 后发表回答