56

我试图找出一种方法来获取给定实体类型的基础 SQL 表名。我已经尝试过 MetadataWorkspace 查询,虽然我可以从对象或存储空间中获取大量信息,但我似乎无法弄清楚如何在两者之间进行映射。

假设我在对象模型中有一个名为 Lookup 的类型 - 我如何在数据库中找到表名 (wws_lookups)?

我可以查询 CSpace 和 SSpace 的所有 EntityType 对象,我可以看到两者都正确列出,但我不知道如何从 CSpace 获取 SSpace。

有没有办法做到这一点?

4

25 回答 25

42

我使用 Nigel 的方法(从 中提取表名.ToTraceString()),但进行了一些修改,因为如果表不在默认 SQL Server 架构 ( dbo.{table-name}) 中,他的代码将无法工作。

我为DbContextObjectContext对象创建了扩展方法:

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

        return objectContext.GetTableName<T>();
    }

    public static string GetTableName<T>(this ObjectContext context) where T : class
    {
        string sql = context.CreateObjectSet<T>().ToTraceString();
        Regex regex = new Regex(@"FROM\s+(?<table>.+)\s+AS");
        Match match = regex.Match(sql);

        string table = match.Groups["table"].Value;
        return table;
    }
}

此处有更多详细信息:
实体框架:从实体获取映射表名称

于 2012-03-18T18:01:52.007 回答
30

编辑 由于 EF 6.1 中的新功能,此答案现已过时:表类型之间的映射先去那里吧!

我对其他答案有疑问,因为我有派生类型。我让这个方法(在我的上下文类中)起作用 - 目前我的模型中只有一层继承

private readonly static Dictionary<Type, EntitySetBase> _mappingCache 
       = new Dictionary<Type, EntitySetBase>();

private EntitySetBase GetEntitySet(Type type)
{
    //If it's a proxy, get the entity type associated with it
    type = ObjectContext.GetObjectType(type);

    if (_mappingCache.ContainsKey(type))
        return _mappingCache[type];

    string baseTypeName = type.BaseType.Name;
    string typeName = type.Name;

    ObjectContext octx = _ObjectContext;
    var es = octx.MetadataWorkspace
                    .GetItemCollection(DataSpace.SSpace)
                    .GetItems<EntityContainer>()
                    .SelectMany(c => c.BaseEntitySets
                                    .Where(e => e.Name == typeName 
                                    || e.Name == baseTypeName))
                    .FirstOrDefault();

    if (es == null)
        throw new ArgumentException("Entity type not found in GetEntitySet", typeName);

    // Put es in cache.
    _mappingCache.Add(type, es);

    return es;
}

internal String GetTableName(Type type)
{
    EntitySetBase es = GetEntitySet(type);

    //if you are using EF6
    return String.Format("[{0}].[{1}]", es.Schema, es.Table);

    //if you have a version prior to EF6
    //return string.Format( "[{0}].[{1}]", 
    //        es.MetadataProperties["Schema"].Value, 
    //        es.MetadataProperties["Table"].Value );
}

internal Type GetObjectType(Type type)
{
    return System.Data.Entity.Core.Objects.ObjectContext.GetObjectType(type);
}

NB 有改进元数据 API的计划,如果这没有得到我们想要的,那么我们可以查看类型和表之间的 EF 代码优先映射

于 2013-09-23T17:06:57.680 回答
9

这里的大多数答案都不适用于派生类。这个可以。并为您提供架构。我在这里结合了答案并对其进行了一些改进(通过取出 First() 和 Single() 之类的东西并将它们转换为 Where() 和 SelectMany() 之类的东西并返回模式名称)。

这适用于 EF 6.1+

// This can return multiple values because it is possible to have one entity correspond to multiple tables when doing entity splitting.
    public static IEnumerable<string> GetTableName<T>(this DbContext context)
    {
        var type = typeof(T);

        var metadata = ((IObjectContextAdapter)context).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) == type);

        // Get the entity set that uses this entity type
        var entitySet = metadata.GetItems(DataSpace.CSpace).Where(x => x.BuiltInTypeKind == BuiltInTypeKind.EntityType).Cast<EntityType>().Single(x => x.Name == entityType.Name);

        // Find the mapping between conceptual and storage model for this entity set
        var entitySetMappings = metadata.GetItems<EntityContainerMapping>(DataSpace.CSSpace).Single().EntitySetMappings.ToList();

        // Find the storage entity sets (tables) that the entity is mapped
        //EntitySet table;

        var fragments = new List<MappingFragment>();

        var mappings = entitySetMappings.Where(x => x.EntitySet.Name == entitySet.Name);

        //if (mappings.Count() > 0)
        //return mappings.SelectMany(m => m.EntityTypeMappings.SelectMany(em => em.Fragments)).ToList();

        fragments.AddRange(mappings.SelectMany(m => m.EntityTypeMappings.SelectMany(em => em.Fragments)));

        fragments.AddRange(entitySetMappings.Where(x => x.EntityTypeMappings.Where(y => y.EntityType != null).Any(y => y.EntityType.Name == entitySet.Name))
            .SelectMany(m => m.EntityTypeMappings.Where(x => x.EntityType != null && x.EntityType.Name == entityType.Name).SelectMany(x => x.Fragments)));

        //if (mapping != null)
        //return mapping.EntityTypeMappings.Where(x => x.EntityType != null).Single(x => x.EntityType.Name == entityType.Name).Fragments;

        fragments.AddRange(entitySetMappings.Where(x => x.EntityTypeMappings.Any(y => y.IsOfEntityTypes.Any(z => z.Name == entitySet.Name)))
        .SelectMany(m => m.EntityTypeMappings.Where(x => x.IsOfEntityTypes.Any(y => y.Name == entitySet.Name)).SelectMany(x => x.Fragments)));

        //var fragments = getFragments();

        // Return the table name from the storage entity set

        var tableNames = fragments.Select(f =>
        {
            var schemaName = f.StoreEntitySet.Schema;
            var tableName = (string)f.StoreEntitySet.MetadataProperties["Table"].Value ?? f.StoreEntitySet.Name;
            var name = $"[{schemaName}].[{tableName}]";
            return name;
        }).Distinct().ToList();

        return tableNames;
    }
于 2018-10-01T23:32:20.267 回答
6

不,不幸的是,使用元数据 API 来获取给定实体的表名是不可能的。

这是因为映射元数据不是公开的,因此无法使用 EF 的 API 从 C-Space 转到 S-Space。

如果你真的需要这样做,你总是可以通过解析 MSL 自己构建地图。这不适合胆小的人,但它应该是可能的,除非您使用QueryViews(这是非常罕见的),在这一点上,出于所有意图和目的,这是不可能的(您必须解析 ESQL ......啊! )

亚历克斯·詹姆斯

微软。

于 2009-12-13T06:04:15.113 回答
6

当您使用注释明确告诉 EF 要使用哪个表名时,为特殊情况添加另一个答案。例如,如果您有:

[Table("tblCompany")]
public class Company
{
}

您可以轻松访问TableAttribute注释以查找表名:

((System.ComponentModel.DataAnnotations.Schema.TableAttribute)typeof(YourNamespace.BO.Company).GetCustomAttribute(typeof(System.ComponentModel.DataAnnotations.Schema.TableAttribute))).Name

这是tblCompany给定的样本。

作为即用型方法:

using System.Reflection;
using System.ComponentModel.DataAnnotations.Schema;

public static string GetTableName<T>() {
    return ((TableAttribute)typeof(T).GetCustomAttribute(typeof(TableAttribute))).Name;
}

(我知道这对 OP 没有帮助,但考虑到问题的标题,人们可能会在这里寻找这个答案。)

于 2018-11-19T11:36:55.443 回答
5

如果您在 EF6 中执行 codefirst,则只需将以下内容添加到您的 dbcontext 类中。

    public string GetTableName(Type entityType)
    {
        var sql = Set(entityType).ToString();
        var regex = new Regex(@"FROM \[dbo\]\.\[(?<table>.*)\] AS");
        var match = regex.Match(sql);

        return match.Groups["table"].Value;
    }
于 2015-01-17T19:44:54.000 回答
5

有一种方法可以使用 EF 删除数据而无需先加载它 我在以下内容中对其进行了更详细的描述:http: //nigelfindlater.blogspot.com/2010/04/how-to-delete-objects-in-ef4 -没有.html

诀窍是将 IQueriable 转换为 ObjectQuery 并使用 ToTraceString 方法。然后编辑生成的 sql 字符串。它有效,但您需要小心,因为您绕过了 EF 为维护依赖关系和约束而设置的机制。但出于性能原因,我认为这样做是可以的......

玩得开心...

奈杰尔...

    private string GetClause<TEntity>(IQueryable<TEntity> clause) where TEntity : class 
    { 
        string snippet = "FROM [dbo].["; 

        string sql = ((ObjectQuery<TEntity>)clause).ToTraceString(); 
        string sqlFirstPart = sql.Substring(sql.IndexOf(snippet)); 

        sqlFirstPart = sqlFirstPart.Replace("AS [Extent1]", ""); 
        sqlFirstPart = sqlFirstPart.Replace("[Extent1].", ""); 

        return sqlFirstPart; 
    } 

   public void DeleteAll<TEntity>(IQueryable<TEntity> clause) where TEntity : class 
    { 
        string sqlClause = GetClause<TEntity>(clause); 
        this.context.ExecuteStoreCommand(string.Format(CultureInfo.InvariantCulture, "DELETE {0}", sqlClause)); 
    } 
于 2010-04-29T06:58:33.990 回答
4

如果您将 T4 模板用于 POCO 类,您可以通过更改 T4 模板来获得它。见片段:

<#  
////////////////////////////////////////////////////////////////////////////////
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();

////////////////////////////////////////////////////////////////////////////////
于 2011-06-03T19:38:02.273 回答
3

A better way is to use the StoreItemCollection from the Metadata. This guy has already provided an example of using it: Get Tables and Relationships

于 2012-11-12T11:30:37.237 回答
3

以下是我使用 LINQ to XML 所能想到的。该代码还获取列名的映射。

var d = XDocument.Load("MyModel.edmx");
XNamespace n = "http://schemas.microsoft.com/ado/2008/09/mapping/cs";
var l = (from etm in d.Descendants()
            where etm.Name == n + "EntityTypeMapping"
            let s = etm.Attribute("TypeName").Value
            select new
            {
                Name = s.Remove(0, s.IndexOf(".") + 1).Replace(")", ""),
                Table = etm.Element(n + "MappingFragment").Attribute("StoreEntitySet").Value,
                Properties = (from sp in etm.Descendants(n + "ScalarProperty")
                            select new
                            {
                                Name = sp.Attribute("Name").Value,
                                Column = sp.Attribute("ColumnName").Value
                            }).ToArray()
            }).ToArray();
于 2012-05-05T18:21:46.787 回答
3

一种可能的解决方法(不是很好,但替代方案也不是......):

var sql = Context.EntitySetName.ToTraceString();

...然后解析SQL,这应该很简单。

于 2009-12-14T15:08:07.400 回答
3

EF 6.1,代码优先:

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;
    }
于 2014-11-30T19:00:25.417 回答
3

将 EF Core 与 SQL Server 一起使用非常简单:

_context.Model.FindEntityType(YOUR_VAR_TYPE).SqlServer().TableName
于 2018-11-22T16:06:51.477 回答
2

您可以尝试 MappingAPI 扩展:https ://efmappingapi.codeplex.com/

它真的很容易使用

context.Db<YourEntityType>().TableName
于 2014-02-24T22:38:24.897 回答
2

这是另一种查找表名的方法。这有点奇怪,但有效。VB:

For Each Table In northwind.MetadataWorkspace.GetItemCollection(New System.Data.Metadata.Edm.DataSpace)
        'adds table name to a list of strings all table names in EF have the project namespace in front of it.'
        If Table.ToString.Contains("namespace of project") then
            'using substring to remove project namespace from the table name.'
            TableNames.Add(Table.ToString.Substring("length of namespace name"))      
        End If
    Next
于 2010-12-20T20:29:51.803 回答
2

版本 3.0 和 3.1 中,它相当简单

var myClassTableName = _context.Model.FindEntityType(typeof(MyClass)).GetTableName();
于 2020-09-27T23:29:15.800 回答
1

这是一个版本,假设您有上下文并且在内存中有一个选定的实体,您需要为其找到真实的表名。

    
    公共静态类 ObjectContextExtentions
    {
        public static string TableNameFor(this ObjectContext context, ObjectStateEntry entry)
        {
            var 泛型 =
                context.GetType().GetProperties().ToList().First(p => p.Name == entry.EntityKey.EntitySetName);
            var objectset = generic.GetValue(context, null);

            var method = objectset.GetType().GetMethod("ToTraceString");
            var sql = (String)method.Invoke(objectset, null);

            var match = Regex.Match(sql, @"FROM\s+\[dbo\]\.\[(?<TableName>[^\]]+)\]", RegexOptions.Multiline);
            如果(匹配。成功)
            {
                返回 match.Groups["TableName"].Value;
            }

            throw new ArgumentException("无法找到表名。");
        }
    }
于 2011-02-06T07:57:55.183 回答
1

使用 EF5 和一点点反射,类似下面的东西应该可以解决问题:

using System;
using System.Collections;
using System.Data.Entity.Infrastructure;
using System.Data.Metadata.Edm;
using System.Linq;
using System.Reflection;

namespace EFHelpers {
    public class EFMetadataMappingHelper {
        public static string GetTableName(MetadataWorkspace metadata, DbEntityEntry entry) {
            var entityType = entry.Entity.GetType();

            var objectType = getObjectType(metadata, entityType);
            var conceptualSet = getConceptualSet(metadata, objectType);
            var storeSet = getStoreSet(metadata, conceptualSet);
            var tableName = findTableName(storeSet);

            return tableName;
        }

        private static EntitySet getStoreSet(MetadataWorkspace metadata, EntitySetBase entitySet) {
            var csSpace = metadata.GetItems(DataSpace.CSSpace).Single();
            var flags = BindingFlags.NonPublic | BindingFlags.Instance;
            var entitySetMaps = (ICollection)csSpace.GetType().GetProperty("EntitySetMaps", flags).GetValue(csSpace, null);

            object mapping = null;

            foreach (var map in entitySetMaps) {
                var set = map.GetType().GetProperty("Set", flags).GetValue(map, null);
                if (entitySet == set) {
                    mapping = map;
                    break;
                }
            }

            var m_typeMappings = ((ICollection)mapping.GetType().BaseType.GetField("m_typeMappings", flags).GetValue(mapping)).OfType<object>().Single();
            var m_fragments = ((ICollection)m_typeMappings.GetType().BaseType.GetField("m_fragments", flags).GetValue(m_typeMappings)).OfType<object>().Single();
            var storeSet = (EntitySet) m_fragments.GetType().GetProperty("TableSet", flags).GetValue(m_fragments, null);

            return storeSet;
        }

        private static string findTableName(EntitySet storeSet) {
            string tableName = null;

            MetadataProperty tableProperty;

            storeSet.MetadataProperties.TryGetValue("Table", true, out tableProperty);
            if (tableProperty == null || tableProperty.Value == null)
                storeSet.MetadataProperties.TryGetValue("http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator:Table", true, out tableProperty);

            if (tableProperty != null)
                tableName = tableProperty.Value as string;

            if (tableName == null)
                tableName = storeSet.Name;

            return tableName;
        }

        private static EntityType getObjectType(MetadataWorkspace metadata, Type entityType) {                
            var objectItemCollection = (ObjectItemCollection)metadata.GetItemCollection(DataSpace.OSpace);

            var edmEntityType = metadata
                .GetItems<EntityType>(DataSpace.OSpace)
                .First(e => objectItemCollection.GetClrType(e) == entityType);

            return edmEntityType;
        }

        private static EntitySetBase getConceptualSet(MetadataWorkspace metadata, EntityType entityType) {
            var entitySetBase = metadata
                .GetItems<EntityContainer>(DataSpace.CSpace)
                .SelectMany(a => a.BaseEntitySets)
                .Where(s => s.ElementType.Name == entityType.Name)
                .FirstOrDefault();

            return entitySetBase;
        }
    }
}

调用它是这样的:

public string GetTableName(DbContext db, DbEntityEntry entry) {
    var metadata = ((IObjectContextAdapter)db).ObjectContext.MetadataWorkspace;
    return EFMetadataMappingHelper.GetTableName(metadata, entry);
}
于 2015-05-14T11:21:06.097 回答
1

如果您只想要一种快速而肮脏的方式来获取表名(并且您在应用程序的代码中不需要它),您可以查看为您的 Model.edmx 生成的 XML。在 edmx:Mappings 部分中找到您的实体,以下行: MappingFragment StoreEntitySet="YourTableName" 将为您提供表的实际名称。

于 2019-04-25T18:47:37.550 回答
1

实际上我也遇到过同样的问题,我制作了一个抽象代码片段,它给了你两个Dictionary<string,List<string>>($table_name,$columns_name_list)。第一个有数据库表 + 列名列表,第二个有本地 EF 实体 + 属性

当然,您可以针对数据类型添加更多检查,顺便说一句,恕我直言,这将迫使您编写极其复​​杂的代码。

损益

PS对不起压缩风格,我是lambda狂热者

using (EFModelContext efmc = new EFModelContext("appConfigConnectionName"))
{
    string schemaName = "dbo";
    string sql = @"select o.name + '.' + c.name
               from sys.all_objects o 
                inner join sys.schemas s on s.schema_id = o.schema_id
                inner join sys.all_columns c on c.object_id = o.object_id
               where Rtrim(Ltrim(o.type)) in ('U') and s.name = @p0";

    Dictionary<string, List<string>> dbTableColumns = new Dictionary<string, List<string>>();

    efmc.Database.SqlQuery<string>(sql, schemaName).Select(tc =>
    {
        string[] splitted = System.Text.RegularExpressions.Regex.Split(tc, "[.]");
        return new { TableName = splitted[0], ColumnName = splitted[1] };
    }).GroupBy(k => k.TableName, k => k.ColumnName).ToList().ForEach(ig => dbTableColumns.Add(ig.Key, ig.ToList()));

    Dictionary<string, List<string>> efTableColumns = new Dictionary<string, List<string>>();

    efTableColumns = ((IObjectContextAdapter)uc).ObjectContext.MetadataWorkspace
                 .GetItems(DataSpace.SSpace).OfType<EntityType>()
                 .ToDictionary( eft => eft.MetadataProperties
                                     .First(mp => mp.Name == "TableName").Value.ToString(),
                                eft => eft.Properties.Select(p => p.Name).ToList());
}
于 2016-12-21T13:42:01.297 回答
1

在使用 Entity Framework Core 2.0+ 的情况下,您可以使用提供的 API 轻松获取关系元数据。

foreach (var entityType in dbContext.Model.GetEntityTypes())
{
    var tableName = entityType.Relational().TableName;
    foreach (var propertyType in entityType.GetProperties())
    {
        var columnName = propertyType.Relational().ColumnName;
    }
}

您需要安装 Microsoft.EntityFrameworkCore.Relational Nuget 包才能使用Relational()方法。

于 2018-10-24T16:35:06.580 回答
0

Alex 是对的——这是元数据 API 中的一个可悲的限制。我必须将 MSL 作为 XML 文档加载,并在处理 C 空间模型时查找 S 空间实体。

于 2009-12-13T06:06:53.973 回答
0

在这里复制我对另一个问题的回答。

如果有人还在寻找,这就是我的做法。这是 DBContext 的扩展方法,它采用类型并返回物理列名及其属性。

这利用对象上下文来获取物理列列表,然后使用“PreferredName”元数据属性将每个列映射到其属性。

由于它使用对象上下文,它会启动一个数据库连接,因此第一次运行会很慢,具体取决于上下文的复杂程度。

public static IDictionary<String, PropertyInfo> GetTableColumns(this DbContext ctx, Type entityType)
{
    ObjectContext octx = (ctx as IObjectContextAdapter).ObjectContext;
    EntityType storageEntityType = octx.MetadataWorkspace.GetItems(DataSpace.SSpace)
        .Where(x => x.BuiltInTypeKind == BuiltInTypeKind.EntityType).OfType<EntityType>()
        .Single(x => x.Name == entityType.Name);

    var columnNames = storageEntityType.Properties.ToDictionary(x => x.Name,
        y => y.MetadataProperties.FirstOrDefault(x => x.Name == "PreferredName")?.Value as string ?? y.Name);

    return storageEntityType.Properties.Select((elm, index) =>
            new {elm.Name, Property = entityType.GetProperty(columnNames[elm.Name])})
        .ToDictionary(x => x.Name, x => x.Property);
}

要使用它,只需创建一个辅助静态类,并添加上述函数;那么它就像调用一样简单

var tabCols = context.GetTableColumns(typeof(EntityType));
于 2017-09-18T03:02:15.263 回答
0

对于 EF6,在这里和周围的其他答案中混合/压缩代码(VB,对不起):

    Public Function getDBTableName(data As myDataModel, ByVal entity As Object) As String
        Dim context = CType(data, IObjectContextAdapter).ObjectContext
        Dim sName As String = entity.GetType.BaseType.Name 'use BaseType to avoid proxy names'
        Dim map = context.MetadataWorkspace.GetItems(Of EntityContainerMapping)(DataSpace.CSSpace).FirstOrDefault

        Return (From esmap In map.EntitySetMappings 
                Select esmap.EntityTypeMappings.First(
                    Function(etm) 
                     etm.EntityType.Name = sName
                   ).Fragments.First.StoreEntitySet.Name).FirstOrDefault
        'TODO: use less .first everywhere but filter the correct ones'
    End Function

它适用于 db-first。
在 .edmx 文件之后相对容易理解。

于 2015-09-30T16:55:32.110 回答
0

您可以使用扩展方法从实体类中获取表名
在这种情况下,您不需要DbContext获取表名,它会在扩展方法中获取它

public static string GetTableName<T>(this T entity) where T : class
{
    var object_context = GetObjectContext(entity);

    if (object_context == null || object_context.TransactionHandler == null)
        return null;

     var dbcontext=object_context.TransactionHandler.DbContext;
    var query= dbcontext.Set(entity.GetType()).ToString();
    var reg = new Regex(@"FROM \[dbo\]\.\[(?<table>.*)\] AS");
    var match = reg.Match(query);

    var tableName= match.Groups["table"].Value;
    return tableName;
}

private static ObjectContext GetObjectContext(object entity)
{
    var field = entity.GetType().GetField("_entityWrapper");

    if (field == null)
        return null;

    var val= field.GetValue(entity);
    var property = val.GetType().GetProperty("Context");
    var context = (ObjectContext)property.GetValue(val, null);

    return context;
}

这是我们到达的地方DbContext

var object_context = GetObjectContext(entity)

用法:

var tableName = entity.GetTableName();
于 2021-04-20T07:23:10.623 回答