C# 将实体映射更改为另一个“;“未知”;运行时的表

C# 将实体映射更改为另一个“;“未知”;运行时的表,c#,sql-server,entity-framework,C#,Sql Server,Entity Framework,我必须编写一个C#应用程序,它与由旧应用程序创建和维护的SQL server数据库一起工作。应用程序每年创建新表,“year属性”位于表名中。它创建的表的数量可能因用户在应用程序中创建的“节”的数量而异。因此,我必须使用像Cwx_DRyz(非常不言自明…)这样的表,其中“wx”可以是部分,“yz”可以是年份。表组的一个示例可以是: C01_DR07 C01_DR08 C01_DR09 C02_DR08 C02_DR09 C03_DR06 C04_DR12 所有这些表都可以表示,例如,客户机。他们

我必须编写一个C#应用程序,它与由旧应用程序创建和维护的SQL server数据库一起工作。应用程序每年创建新表,“year属性”位于表名中。它创建的表的数量可能因用户在应用程序中创建的“节”的数量而异。因此,我必须使用像Cwx_DRyz(非常不言自明…)这样的表,其中“wx”可以是部分,“yz”可以是年份。表组的一个示例可以是:

C01_DR07

C01_DR08

C01_DR09

C02_DR08

C02_DR09

C03_DR06

C04_DR12

所有这些表都可以表示,例如,客户机。他们将是来自不同部门和不同年份的客户,但客户结构相同

我的问题是:我是否可以有一个客户端实体来处理所有这些表,并在运行时更改从一个表到另一个表的映射?标题是“未知”,因为我在运行前不知道这些表

我发现的最相似的问题是,答案是使用“每个具体类型的表继承”,但它对我的情况没有用处

PS:EF版本4.3.1和VS2010

编辑:表没有主键。。。它们中的大多数都有列,支持它们具有唯一的值(整数或字符串)。

如果使用“代码优先”,则可以根据需要创建映射。当您创建的映射与数据库匹配时,这也适用于现有数据库

因此,无论何时创建上下文,都可以构建要映射到的字符串(tablename)

“代码优先”的一些代码示例以及如何开始:

数据库上下文:

public DbSet<YourEntity> YourEntities { get; set; }
...

// this is called when the db gets created and does the configuration for you => maybe not needed in your case
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    ConfigurationRegistrar configurationRegistrar = modelBuilder.Configurations;

    new GeneralEntitiesConfiguration(configurationRegistrar);
}
YourEntityConfiguration是一个类,在此类中我拥有此实体的所有配置:

public class YourEntityConfiguration : EntityTypeConfiguration<YourEntity>
{
    public YourEntityConfiguration ()
    {
        ToTable("WhatEverYouLike"); // here you can do any magic to map this entity to a table, just make sure that your properties are mapped to the correct colums
        Property(entity => entity.Id).HasColumnName("YouColumnName");

        //and here you also have to do the other configurations
    }
}
公共类YourEntityConfiguration:EntityTypeConfiguration { 公共YourEntityConfiguration() { ToTable(“WhatEverYouLike”);//在这里,您可以使用任何魔法将该实体映射到表,只需确保您的属性映射到正确的列即可 属性(entity=>entity.Id); //在这里,您还必须进行其他配置 } } 在应用程序启动时(或在第一次初始化上下文之前),必须初始化数据库。因此,可以使用初始值设定项检查数据库并处理差异。内置有“DropCreateDatabaseAlways”或“DropCreateDatabaseIfModelChanges”=>您需要创建自己的,忽略任何差异。在我的示例中,我创建了一个在模型不同时抛出异常的示例(我想在第一次尝试时使用scipts处理模型更改):

//在我第一次调用上下文之前,您可以忽略连接字符串
DbContextInitializer.Init(conString);
公共静态类DbContextInitializer
{
公共静态void Init(字符串连接字符串)
{
SetInitializer(新的CreatedBthroweExceptionIfModelDifferInitializer());
使用(var dbContenxt=newmydbcontext(connectionString))
{
尝试
{
dbContenxt.Database.Initialize(true);
}
捕获(DatabaseModelDiffersException DifferSexception)
{
//一些魔法。。。
}
捕获(例外情况除外)
{
//TODO:日志
投掷;
}
}
}
公共类CreateDbThroweExceptionIfModelDifferInitializer:IDatabaseInitializer,其中TContext:DbContext
{
public void InitializeDatabase(TContext上下文)
{
使用(新TransactionScope(TransactionScopeOption.Suppress))
{
如果(!context.Database.Exists())
context.Database.Create();
}
如果(!context.Database.CompatibleWithModel(true))
{
抛出新的DatabaseModelDifferenceException(“DatabaseModelDifferences!”);
}
}
受保护的虚拟空种子(TContext上下文)
{
//如果愿意,可以创建数据
}
}
//只是一个例外,我以后会用的
公共类DatabaseModelDifferersException:异常
{
公共数据库模型差异异常(字符串msg):基(msg)
{}
}
}
希望你有一个想法,你可以处理动态表名与实体框架!
如果有更多问题,请提问;)

映射不必与数据库匹配,因为并非所有用户都创建了所有“实体”(表集)。它是强制性的完全匹配吗?无论如何,我会很感激这些样品。我也很有兴趣看看你们的样品。当你拿到它们的时候打电话给我。丢失PKs可能是个问题。。。但是使用代码优先,你可以在代码中设置PK,我不知道这个密钥是否也必须在数据库中…嘿。。。对不起,我在周末没有时间(我的婚礼还有两周)从现在开始收集我写的一个小测试项目的所有部分。给我半个小时左右,别担心,再次感谢你的帮助。我一直在做一些研究,似乎它已经为主键做好了准备。
public class YourEntityConfiguration : EntityTypeConfiguration<YourEntity>
{
    public YourEntityConfiguration ()
    {
        ToTable("WhatEverYouLike"); // here you can do any magic to map this entity to a table, just make sure that your properties are mapped to the correct colums
        Property(entity => entity.Id).HasColumnName("YouColumnName");

        //and here you also have to do the other configurations
    }
}
//before using the context the first time i'm calling, you can ignore the connection string
DbContextInitializer.Init(conString);

public static class DbContextInitializer
{
    public static void Init (string connectionString)
    {
        Database.SetInitializer(new CreateDbThrowExceptionIfModelDiffersInitializer<SMDbContext>());

        using(var dbContenxt = new MyDbContext(connectionString))
        {
            try
            {
                dbContenxt.Database.Initialize(true);
            }
            catch(DatabaseModelDiffersException diffException)
            {
                // some magic...
            }
            catch(Exception ex)
            {
                // TODO: log
                throw;
            }
        }
    }

    public class CreateDbThrowExceptionIfModelDiffersInitializer<TContext> : IDatabaseInitializer<TContext> where TContext : DbContext
    {
        public void InitializeDatabase(TContext context)
        {
            using (new TransactionScope(TransactionScopeOption.Suppress))
            {
                if (!context.Database.Exists())
                    context.Database.Create();
            }

            if (!context.Database.CompatibleWithModel(true))
            {
                throw new DatabaseModelDiffersException("Database Model differs!");
            }
        }

        protected virtual void Seed(TContext context)
        {
            // create data if you like
        }
    }

    // just an exception i'm using for later useage
    public class DatabaseModelDiffersException : Exception
    {
        public DatabaseModelDiffersException(string msg) : base(msg)
        {}
    }
}