免责声明:我在 C# / WPF / EFC 方面相对缺乏经验
我正在开发一个用 C# 编写的 WPF 应用程序,它需要在数据库中存储一些数据。为了存储这些数据,我想使用 Entity Framework Core。该应用程序将使用一个共享数据库实例,其他应用程序也使用该实例。每个应用程序都有自己的表前缀,因此我的应用程序也需要有自己的表前缀。
更新
我想要实现的是从
Parent
继承的所有对象都存储在同一个表中。当我从表中“加载”数据时,我想要一个有关 Child
类的实例化实例。本身不可能/不应该有 Parent
的实例。
添加表前缀
我在我的
OnModelCreating
类的 DbContext
函数中添加了表前缀(到目前为止效果很好):
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
modelBuilder.Entity(entity.ClrType).ToTable(tablePrefix + entity.GetTableName());
}
实现“每个层次结构表”
实现表前缀后,我根据这个描述实现了TPHhttps://www.learnentityframeworkcore.com/inheritance/table-per-hierarchy
这是实现:
public abstract class Parent
{
// ...
}
public class ChildA : Parent
{
// ...
}
public class ChildB : Parent
{
// ...
}
internal class EcroDbContext : DbContext
{
private string tablePrefix = "APP_PREFIX_";
public DbSet<Schedule> Schedules { get; set; } = null;
public DbSet<ChildA> ChildA { get; set; } = null;
public DbSet<ChildBIpp> ChildB { get; set; } = null;
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
string user = "xxx";
string password = "xxx";
string dbName = "xxx";
string conString = "User Id=" + user + ";Password=" + password + ";Data Source=" + dbName;
optionsBuilder.UseOracle(conString, x => x.MigrationsHistoryTable(tablePrefix + "ef_migration_history", null));
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Parent>().ToTable(tablePrefix + "Jobs");
// Add prefix to each table.
// When I remove this foreach, the TPH works fine
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
modelBuilder.Entity(entity.ClrType).ToTable(tablePrefix + entity.GetTableName());
}
}
}
当我运行
Add-Migration InitialMigration
时,我收到此错误:
无法创建类型为“”的“DbContext”。异常“‘ChildB’和‘ChildA’都映射到表‘APP_PREFIX_APP_PREFIX_APP_PREFIX_Jobs’。非 TPH 层次结构(没有鉴别器的层次结构)中的所有实体类型必须映射到不同的表。
错误指出“非 TPH 中的所有实体类型必须映射不同的表”,但我认为我已经为上述类实现了 TPH。首先我以为我实现了错误,但是当我从
OnModelCreating
部分中删除表前缀部分时,它似乎工作正常。
这意味着表前缀实现会导致
TPH
实现出现问题。我该如何解决这个错误?
[已解决]
我注意到
Jobs
表的前缀添加了 3 次。我该如何解决这个问题?
我通过检查名称是否已包含前缀(如 @ Svyatoslav Danyliv 建议)。
foreach (var entity in (modelBuilder.Model.GetEntityTypes()))
{
if (!entity.GetTableName().Contains(tablePrefix))
{
modelBuilder.Entity(entity.ClrType).ToTable(tablePrefix + entity.GetTableName());
}
}
这也因某种原因解决了TPH问题。现在它就像一个魅力。