我必须编写一个 C# 应用程序来处理由旧应用程序创建和维护的 SQL 服务器数据库。该应用程序每年创建新表,并且“年份属性”在表名中。它创建的表的数量可能会有所不同,具体取决于用户在应用程序中创建的“部分”的数量。所以,我必须使用像 Cwx_DRyz 这样的表(非常不言自明......),其中“wx”可以是部分,“yz”可以是年份。表格组的示例可以是:
C01_DR07
C01_DR08
C01_DR09
C02_DR08
C02_DR09
C03_DR06
C04_DR12
所有这些表都可以代表,例如,客户。他们将是来自不同部门和年份的客户,但具有相同结构的客户。
我的问题是:我能否拥有一个客户端实体来处理所有这些表并在运行时将映射从一个表更改为另一个表?标题说“未知”是因为我不知道运行前的表。
我发现的最相似的问题是Entity Framework map multiple tables to one entity答案是使用“每个具体类型继承表”,但它对我的情况没有用。
PS: EF 版本 4.3.1 和 VS2010
编辑:这些表没有主键......它们中的大多数都有被认为具有唯一值(整数或字符串)的列。
最佳答案
如果您使用“代码优先”,您可以根据需要创建映射。当您创建的映射与数据库匹配时,这也适用于现有数据库。
因此,无论何时创建上下文,您都可以构建要映射到的字符串(表名)。
“代码优先”的一些代码示例以及如何开始:
DbContext:
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);
}
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
}
}
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
}
}
在应用程序启动时(或在您第一次初始化上下文之前),您必须初始化数据库。因此,您可以使用初始化程序来检查数据库并处理差异。内置有“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)
{}
}
}
希望您已经了解可以使用 Entity Framework 处理动态表名! 如果还有更多问题,请提问 ;)
关于c# - 在运行时将实体映射更改为另一个 "unknown"表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11142530/