【问题标题】:Entity Framework | Code First - Get Name Of Created Table实体框架 |代码优先 - 获取创建表的名称
【发布时间】:2016-06-07 04:37:33
【问题描述】:

有可能吗?我知道,当我指定 TableAttribute 时,我可以获得名称,但即使这样,当我让框架管理名称时,它也应该是可能的。

提前致谢。

【问题讨论】:

    标签: entity-framework entity-framework-4 entity-framework-4.1 code-first


    【解决方案1】:

    我最终得到了这个:

    public static class DbContextExt
    {
        public static string GetTableName<T>(this DbContext context) where T : class
        {
            var type = typeof(T);
            var entityName = (context as System.Data.Entity.Infrastructure.IObjectContextAdapter).ObjectContext.CreateObjectSet<T>().EntitySet.Name;
            var tableAttribute = type.GetCustomAttributes(false).OfType<System.ComponentModel.DataAnnotations.Schema.TableAttribute>().FirstOrDefault();
    
            return tableAttribute == null ? entityName : tableAttribute.Name;
        }
    }
    

    这是两个答案的混合体:DBset tabel name

    【讨论】:

    • 这个不错。我使用您的答案派生出一个可以处理我将很快发布的 2/3 继承方法的方法。 +1
    【解决方案2】:

    执行此操作的正确方法是使用以下页面中的GetTableName 方法:http://romiller.com/2014/04/08/ef6-1-mapping-between-types-tables/

    这包括对元标记和模型构建器.ToTable() 更改的支持。本页示例基本返回DbSet属性名,不一定是数据库中的表名。

    例如,如果您有:

    DbSet<Config> Settings { get; set; }
    

    当实际数据库表名称为“Configs”时,此页面上的代码将返回表名称的“设置”。如果你使用,你会遇到同样的问题:

    modelBuilder.Entity<Config>().ToTable("UserSettings")
    

    使用提供的链接中的代码可以缓解所有这些问题。这里写成一个扩展:

    public static class DbContextExtensions
    {
        public static string GetTableName<T>(this DbContext context) where T : class
        {
            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<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;
        }
    }
    

    【讨论】:

      【解决方案3】:

      如果你不使用TableAttribute或fluent api来定义表名,则该名称将根据上下文中DbSet属性的名称推断出来。在这种情况下,唯一可以修改名称的是默认使用的复数约定。

      如果你有:

      public class Context : DbContext
      {
          public DbSet<User> Users { get; set; }
      }
      

      该表应命名为Users

      【讨论】:

      • 所以如果它是 DbSet "SomethingFancyNotEvenEnglish" {get; set;} 它将如何命名表?还是用户?
      • 不,可能是SomethingFancyNotEvenEnglishs
      • 正确答案是用户。 EF 从类型推断表名,而不是属性名。
      【解决方案4】:

      这应该处理每个类型的表和每个层次结构的表继承。

      见: http://weblogs.asp.net/manavi/archive/2010/12/24/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table-per-hierarchy-tph.aspx

      诀窍是遍历继承树,直到找到覆盖的 Table 属性或非对象基类型。如果可以从未映射到表的类继承,这可能会失败……我不确定。如果您可以对一个类执行 [NotMapped],那么我们只需要更改 GetTableDefType 方法以在这种情况下向后走一次。

         private static Type GetTableDefType(this Type t, out TableAttribute attr) {
              attr = null;
              if (t == typeof(Object)) { throw new ArgumentException(); }
              var tType = t;
              while (true) {               
                  attr = tType.GetCustomAttributes(false).OfType<TableAttribute>().FirstOrDefault();
                  if (attr != null) { return tType; }
      
                  if (tType.BaseType == null || tType.BaseType == typeof(Object)) { return tType; }
                  tType = tType.BaseType;
              }
          }
          public static string GetTableName(this DbContext context, Type type)  {
              TableAttribute testAttr = null;
              var baseType = type.GetTableDefType(out testAttr);
      
              if (testAttr != null) { return testAttr.TableName; }
      
              var propBinding = BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty;
              var objectContext = context.GetType().GetInterface("System.Data.Entity.Infrastructure.IObjectContextAdapter").GetProperty("ObjectContext", propBinding).GetValue(context, null);
              var objectSet = objectContext.GetType().GetMethod("CreateObjectSet", new Type[0]).MakeGenericMethod(baseType).Invoke(objectContext, null);
              return ((EntitySet)objectSet.GetType().GetProperty("EntitySet", propBinding).GetValue(objectSet, null)).Name;
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-05
        • 1970-01-01
        相关资源
        最近更新 更多