Entity framework EF 4.1,POCO:有没有办法在运行时获取表名以避免硬代码?

Entity framework EF 4.1,POCO:有没有办法在运行时获取表名以避免硬代码?,entity-framework,entity-framework-4,poco,Entity Framework,Entity Framework 4,Poco,我在实体框架中使用POCO。在最新的EF版本中,是否有任何直接或间接的方式在运行时获取表名以避免硬代码值 我需要在自定义数据库初始值设定项中使用它来运行如下代码: context.Database.ExecuteSqlCommand( string.Format("DBCC CHECKIDENT ({0}, RESEED, {1})", tableName, newSeed)) 感谢POCO意味着您可以在数据模型中使用“普通旧”CLR对象(POCO),例如现有的域对象。这些POCO数据

我在实体框架中使用POCO。在最新的EF版本中,是否有任何直接或间接的方式在运行时获取表名以避免硬代码值

我需要在自定义数据库初始值设定项中使用它来运行如下代码:

context.Database.ExecuteSqlCommand(
    string.Format("DBCC CHECKIDENT ({0}, RESEED, {1})", tableName, newSeed))
感谢

POCO意味着您可以在数据模型中使用“普通旧”CLR对象(POCO),例如现有的域对象。这些POCO数据类(也称为持久性无关对象)映射到数据模型中定义的实体,根据定义,它们不应该与数据库实现细节直接相关。但是,您可以使用常量类和Fluent映射来更好地满足您的需求

您的常量类实现

public static class Constant
{
 public const string CreditCustomer = "dbo.CreditCustomer";
}
你的映射是这样的

builder.Entity<Customer>() 
.HasKey(c => c.ID) 
.MapSingleType(c => new { 
     cid = c.ID, 
     nme = c.Name 
  } 
) 
.ToTable(Constant.Table.CreditCustomer);

看看这个讨论有多“活跃”,我觉得这个功能在EF的当前版本中没有提供。我希望这项功能将在EF的未来版本中可用。

这段代码有用吗

        var query = from meta in context.MetadataWorkspace.GetItems(DataSpace.SSpace)
          .Where(m => m.BuiltInTypeKind == BuiltInTypeKind.EntityType)
        let properties = meta is EntityType ? (meta as EntityType).Properties : null
        select new
        {
          TableName = (meta as EntityType).Name,
          Fields = from p in properties
                   select new
                   {
                     FielName = p.Name,
                     DbType = p.TypeUsage.EdmType.Name
                   }
        };

我的工作假设您的上下文与我的上下文类似,当您向上下文添加DbSet时,每个表名都是从类名生成的。如果是这样的话,你可以通过反思来实现你的目标,尽管这有点难看:

public class MyContext : DbContext
{
    public MyContext() : base("MyDatabase")
    {
    }

    public DbSet<Video> Video { get; set; }
    public DbSet<VideoRating> Rating { get; set; }
    public DbSet<User> User { get; set; }

            protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }

    public class Initializer : IDatabaseInitializer<DashVaultContext>
    {
        public void InitializeDatabase(MyContext context)
        {
            if (!context.Database.Exists())
            {
                context.Database.Create();

                PropertyInfo[] propertyInfos = typeof(MyContext).GetProperties(BindingFlags.DeclaredOnly |
                BindingFlags.Public | BindingFlags.Instance);

                var newSeed = 1000; // Or whatever is appropriate

                foreach (PropertyInfo propertyInfo in propertyInfos)
                {
                    var tableName = propertyInfo.PropertyType.GetGenericArguments()[0].Name;
                    context.Database.ExecuteSqlCommand(
                        string.Format("DBCC CHECKIDENT ({0}, RESEED, {1})", tableName, newSeed));
                }
            }
        }
    }
}
公共类MyContext:DbContext
{
public MyContext():base(“MyDatabase”)
{
}
公共数据库集视频{get;set;}
公共数据库集评级{get;set;}
公共数据库集用户{get;set;}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove();
}
公共类初始值设定项:IDatabaseInitializer
{
public void初始化数据库(MyContext上下文)
{
如果(!context.Database.Exists())
{
context.Database.Create();
PropertyInfo[]propertyInfos=typeof(MyContext).GetProperties(BindingFlags.DeclaredOnly|
BindingFlags.Public | BindingFlags.Instance);
var newSeed=1000;//或任何适当的值
foreach(PropertyInfo PropertyInfo in propertyInfos中的PropertyInfo)
{
var tableName=propertyInfo.PropertyType.GetGenericArguments()[0].Name;
context.Database.ExecuteSqlCommand(
Format(“DBCC CHECKIDENT({0},重新设定种子,{1})”,tableName,newSeed);
}
}
}
}
}

更新:我删除了复数化攻击,只是在生成的表名中关闭了复数化(请参阅OnModelCreating覆盖)

你能从数据库初始值设定项中发布一个示例并解释你想要更改什么吗?@marc_s:context.database.ExecuteSqlCommand(string.Format(“DBCC CHECKIDENT({0},RESEED,{1})”,tableName,newSeed))请不要将代码和内容放入注释中-这真的很难阅读。取而代之的是:通过编辑来更新您的原始问题,并提供更多信息!如果未使用
ToTable(“tableName”)
EF将采用tableName作为类名。如果你改变你的域名类名,EF也会改变初始化器中的表名。对,这是我一直在使用的解决方法。问题是通过EF配置类找到表名的任何直接方法来摆脱常量类,我不希望为每个表创建常量,我希望我的表名在更改相应的域类名时自动更新。什么是MetadataWorkspace?DbContext没有这样的属性检查以下链接。它描述了从DbContext链接到ObjectContext的可能方法,其中MetadataWorkspace是可用的:对,我们的一些类映射到带有“s”的表名,其中一些没有。无论如何,谢谢你的想法。@YMC我更新了我的答案,使之更加健壮-我只是在ModelCreating上做了一些修改,以关闭表名的复数化。这样,类的名称始终是表的名称,我的答案将始终有效。当然,这是假设你同意表名始终是类名。好吧,虽然解决这个任务似乎有点奇怪,但至少对我来说是可行的。谢谢
public class MyContext : DbContext
{
    public MyContext() : base("MyDatabase")
    {
    }

    public DbSet<Video> Video { get; set; }
    public DbSet<VideoRating> Rating { get; set; }
    public DbSet<User> User { get; set; }

            protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }

    public class Initializer : IDatabaseInitializer<DashVaultContext>
    {
        public void InitializeDatabase(MyContext context)
        {
            if (!context.Database.Exists())
            {
                context.Database.Create();

                PropertyInfo[] propertyInfos = typeof(MyContext).GetProperties(BindingFlags.DeclaredOnly |
                BindingFlags.Public | BindingFlags.Instance);

                var newSeed = 1000; // Or whatever is appropriate

                foreach (PropertyInfo propertyInfo in propertyInfos)
                {
                    var tableName = propertyInfo.PropertyType.GetGenericArguments()[0].Name;
                    context.Database.ExecuteSqlCommand(
                        string.Format("DBCC CHECKIDENT ({0}, RESEED, {1})", tableName, newSeed));
                }
            }
        }
    }
}