实体框架| Code First - 获取创建表的名称

问题描述:

可能吗?当我指定TableAttribute时,我知道我可以得到这个名字,但是当我让框架管理这个名字时,它应该是可能的。实体框架| Code First - 获取创建表的名称

在此先感谢。

如果您不使用TableAttribute或流利的api来定义表名,则将从上下文中DbSet属性的名称推断出该名称。在这种情况下唯一可以修改名称的是缺省使用的多元化约定。

所以,如果您有:

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

表应该被命名为Users

+1

所以如果是DbSet “SomethingFancyNotEvenEnglish”{get;设置;}它如何命名表?还是用户? – hazimdikenli 2011-05-10 12:42:11

+1

不,它可能是'SomethingFancyNotEvenEnglishs' – 2011-05-10 13:17:51

+7

正确的答案是用户。 EF从类型推断表名,而不是属性名。 – 2012-08-24 09:29:06

我结束了与此:

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

+0

这很不错。我用你的答案来派生一个将处理2/3继承方法的东西,我将很快发布。 +1 – Adam 2012-02-16 15:38:09

这应该处理Table per Type和Table per Hierarchy继承。

参见: 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

关键是要遍历继承树,直到找到一个被覆盖的表属性或非对象的基本类型。这可能会失败,如果它可能从一个没有映射到表的类继承...我不知道。如果你可以在一个类上做[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; 
    } 

正确的方式做,这是从以下页面使用GetTableName方法:http://romiller.com/2014/04/08/ef6-1-mapping-between-types-tables/

这包括meta标签和模型构建.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; 
    } 
}