У меня есть пять сущностей. Я хочу избежать использования стратегии TPH, встроенной в EF Core, поскольку полученная таблица представляет собой полный беспорядок.
Пять сущностей можно показать так:
public abstract class A {
public int Id { get; set; }
}
public class B : A {
public string Foo { get; set; }
}
public class C : A {
public string Bar { get; set; }
}
public class DA<TType> where TType : A {
public int DId { get; set; }
public D D { get; set; }
public int AId { get; set; }
public TType A { get; set; }
}
public class D {
public int Id { get; set; }
}
Что нужно извлечь отсюда: B и C наследуют от A, DA - тип прокси для отношения n: m между D и A (имеется в виду B и C), я пропустил навигационные свойства.
My DbContext выглядит так:
public class ApplicationDbContext : DbContext
{
public DbSet<D> Ds { get; set; }
public DbSet<B> Bs { get; set; }
public DbSet<DA<B>> BDAs { get; set; }
public DbSet<C> Cs { get; set; }
public DbSet<DA<C>> CDAs { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
// Configure B to D with n:m relation via DA
builder.Entity<DA<B>>()
.HasKey(d => new { d.DId, d.AId });
builder.Entity<DA<B>>()
.HasOne(d => d.D)
.WithMany()
.HasForeignKey(d => d.DId);
builder.Entity<DA<B>>()
.HasOne(d => d.A)
.WithMany()
.HasForeignKey(d => d.AId);
// Configure C to D with n:m relation via DA
builder.Entity<DA<C>>()
.HasKey(d => new { d.DId, d.AId });
builder.Entity<DA<C>>()
.HasOne(d => d.D)
.WithMany()
.HasForeignKey(d => d.DId);
builder.Entity<DA<C>>()
.HasOne(d => d.A)
.WithMany()
.HasForeignKey(d => d.AId);
}
}
Теперь на мои вопросы:
- Теперь весь пример - моя текущая реализация для достижения этой цели. К сожалению, это очень много кода, который нужно добавить для каждой дополнительной сущности. Есть ли какой-то механизм / подход (помимо TPH, который использует одну таблицу), который позволяет мне сделать это:
// Reusing classes A, B, C and D from above
public class DA {
public int AId { get; set; }
public A A { get; set; }
public int DId { get; set; }
public D D { get; set; }
}
// Then only have one DbSet in the ApplicationDbContext with this:
public DbSet<DA> DAs { get; set; }
Я вижу необходимость в дискриминаторе или подобном для обработки разных таблиц, но не могу придумать никакого подхода, чтобы справиться с этим прямо сейчас. У вас есть идея?
Отдельно: могу ли я применить конфигурацию к A и заставить B и C автоматически наследовать эту конфигурацию? Я мог бы сделать это, используя атрибуты, но хочу избежать ссылки на EF Core в моем доменном проекте. Я имею в виду: есть ли способ справиться с этим с помощью Fluent API?