Disclaimer: I'm relatively inexperienced in C# / WPF / EFC
I'm working on a WPF application written in C# which needs to store some data in a database. To store this data, I want to use Entity Framework Core. The application will uses a shared database instance which is also used by other applications. Each application has its own table prefix so my application needs to have an own table prefix as well.
Update
What I want to achieve is that all objects which are inherited from Parent
are stored in the same table. When I "load" data from the table I want an instantiated instance of concerning Child
class. It is/should not possible to have instances of Parent
themself.
Add table prefix
I added the table prefixes in the OnModelCreating
function of my DbContext
class (this works great so far):
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
modelBuilder.Entity(entity.ClrType).ToTable(tablePrefix + entity.GetTableName());
}
Implement "Table per Hierarchy"
After implementing the table prefix, I implemented the TPH according to this description https://www.learnentityframeworkcore.com/inheritance/table-per-hierarchy
This is the implementation:
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());
}
}
}
When I run Add-Migration InitialMigration
, I got this error:
Unable to create a 'DbContext' of type ''. The exception 'Both 'ChildB' and 'ChildA' are mapped to the table 'APP_PREFIX_APP_PREFIX_APP_PREFIX_Jobs'. All the entity types in a non-TPH hierarchy (one that doesn't have a discriminator) must be mapped to different tables.
The error says that "all entity types in a non-TPH must map a different table", but I thought I had implemented TPH for the mentioned classes. First I thought that I implemented it wrong, but when I remove the table prefix part from the OnModelCreating
part, it seems to work fine.
This means that the table prefix implementation causes issues for the TPH
implementation. How can I solve this error?
[SOLVED]
I notice that the prefix is added 3 times for the Jobs
table. How can I solve this?
I solved the naming issue by checking if the name already contains the prefix (like @ Svyatoslav Danyliv suggested).
foreach (var entity in (modelBuilder.Model.GetEntityTypes()))
{
if (!entity.GetTableName().Contains(tablePrefix))
{
modelBuilder.Entity(entity.ClrType).ToTable(tablePrefix + entity.GetTableName());
}
}
This also solved the TPH issue for some reason. It works like a charm now.