在运行时将实体映射更改为另一个"未知"表

Car*_*osJ 5 c# sql-server entity-framework

我必须编写一个C#应用程序,该应用程序适用于由旧应用程序创建和保留的SQL服务器数据库.应用程序每年创建新表,"年份属性"在表名中.它创建的表的数量可能会有所不同,具体取决于用户在应用程序中创建的"部分"的数量.所以,我必须使用像Cwx_DRyz这样的表(非常自我解释......),其中"wx"可以是部分,"yz"将是年份.表组的示例可以是:

C01_DR07

C01_DR08

C01_DR09

C02_DR08

C02_DR09

C03_DR06

C04_DR12

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

我的问题是:我可以让客户端实体处理所有这些表并在运行时将映射从一个更改为另一个吗?标题说"未知",因为我不知道运行前的表.

我发现的最相似的问题是实体框架将多个表映射到一个实体,答案是使用"每个具体类型的表继承",但它对我的情况没有用.

PS:EF版本4.3.1和VS2010

编辑:表没有主键...他们中的大多数都有专门的列(整数或字符串).

Dom*_*fer 4

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

因此,每当您创建上下文时,您都可以构建要映射到的字符串(表名)。

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

数据库上下文:

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);
}
Run Code Online (Sandbox Code Playgroud)

GeneralEntitiesConfiguration 是我用来处理配置的类,只不过是一个助手,如下所示:

public class GeneralEntitiesConfiguration
{
    public GeneralEntitiesConfiguration(ConfigurationRegistrar configurationRegistrar)
    {
        configurationRegistrar.Add(new YourEntityConfiguration());
        //and additional configurations for each entity, just to splitt it a bit and have it more read and maintenance able
    }
}
Run Code Online (Sandbox Code Playgroud)

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
    }
}
Run Code Online (Sandbox Code Playgroud)

在应用程序启动时(或在第一次初始化上下文之前),您必须初始化数据库。因此,您可以使用初始化程序来检查数据库并处理差异。内置诸如“DropCreateDatabaseAlways”或“DropCreateDatabaseIfModelChanges”之类的内容=>您需要创建自己的内容,它会忽略任何差异。在我的示例中,我创建了一个在模型不同时仅抛出异常的示例(我想在第一次尝试时使用 scipts 处理模型更改):

//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)
        {}
    }
}
Run Code Online (Sandbox Code Playgroud)

希望您知道可以使用实体框架处理动态表名称!如果还有更多问题,请询问;)