如何获取实体框架中表的架构名称?

问题描述 投票:0回答:7

我使用用户模式分离技术来分离数据库中的表。您能告诉我如何获取实体框架中实体集(表)的架构名称吗?谢谢。

c# entity-framework schema entity
7个回答
4
投票

这现在一定是一个老话题了,但对于那些仍然潜伏在 EF6+ 中的人(如不是 EF 核心),基于 Rowan Miller 当年的同样出色的博客 post,请检查我的方法来呈现一些内容有关给定实体的元信息

public class DbTableMeta
{
    public string Schema { get; set; }

    public string Name { get; set; }

    public IEnumerable<string> Keys { get; set; }
}


public static DbTableMeta Meta(this DbContext context, Type type)
{
    var metadata = ((IObjectContextAdapter) context).ObjectContext.MetadataWorkspace;

    // Get the part of the model that contains info about the actual CLR types
    var items = (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(p => items.GetClrType(p) == type);

    // Get the entity set that uses this entity type
    var entitySet = metadata
        .GetItems<EntityContainer>(DataSpace.CSpace)
        .Single()
        .EntitySets
        .Single(p => p.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(p => p.EntitySet == entitySet);

    // Find the storage entity set (table) that the entity is mapped
    var table = mapping
        .EntityTypeMappings.Single()
        .Fragments.Single()
        .StoreEntitySet;

    return new DbTableMeta
    {
        Schema = (string) table.MetadataProperties["Schema"].Value ?? table.Schema,
        Name = (string) table.MetadataProperties["Table"].Value ?? table.Name,
        Keys = entityType.KeyMembers.Select(p => p.Name),
    };
}

2
投票

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 (?<table>.*) AS");
        Match match = regex.Match(sql);

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

使用 ObjectContext 对象:

ObjectContext context = ....;
string table = context.GetTableName<Foo>();

使用 DbContext 对象:

DbContext context = ....;
string table = context.GetTableName<Foo>();

更多信息在这里:

实体框架:从实体获取映射表名称


2
投票

我发现以下博客条目解释了如何从元数据工作空间获取该信息:

https://romiller.com/2014/04/08/ef6-1-mapping- Between-types-tables/

这是发挥魔力的函数:

public static string GetTableName(Type type, DbContext context)
{
    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<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
    var table = mapping
        .EntityTypeMappings.Single()
        .Fragments.Single()
        .StoreEntitySet;

    // Return the table name from the storage entity set
    return (string)table.MetadataProperties["Table"].Value ?? table.Name;
}

1
投票

对于那些使用代码优先的人,模式名称在上下文的

OnModelCreating
覆盖中设置;

public static readonly string DefaultSchemaName = "Entities";

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.HasDefaultSchema(DefaultSchemaName);

    ...

所以你应该能够从代码中的其他地方引用

DefaultSchemaName

如果您一开始就没有构建模型上下文和 EF 内容,那么这个答案就不太明显。


0
投票

用于截断表的示例,其中需要表名称和架构。

public void ClearTable<T>() where  T: class
    {
        var dbContext = (DbContext) _dbContext;
        
        var annotations = dbContext.Model.FindEntityType(typeof(T)).GetAnnotations().ToList();

        var tableName = annotations.First(c => c.Name == "Relational:TableName").Value.ToString();
        var schema = annotations.First(c => c.Name == "Relational:Schema").Value.ToString();

        dbContext.Database.ExecuteSqlRaw($"truncate table {schema}.{tableName}");

    }

0
投票
当 Type 为

Model.{Entity}type.BaseType

Object 时,
Approved
答案为 true,但如果 Type 为
System.Data.Entity.DynamicProxies
,您将得到异常

序列不包含匹配元素

要解决此问题,只需像这样修改实体类型

var entityType = metadata
                    .GetItems<EntityType>(DataSpace.OSpace)
                    .Single(e => objectItemCollection.GetClrType(e) == type || objectItemCollection.GetClrType(e) == type.BaseType);

-3
投票

使用Entity Framework 6.1.3,您可以通过以下方式查询方案和表名:

  string tableNameWithScheme = context.Db<T>().Schema+"."+context.Db<T>().TableName;

其中 T 是实体的类型,上下文是派生的 System.Data.Entity.DBContext 的实例。

© www.soinside.com 2019 - 2024. All rights reserved.