EF Core中具有TPH继承的多对多



如果联接表的一侧是表中每个层次结构设置的派生类,那么我在用EF核心设置多对多联接表时遇到了问题。

设置如下:

class Chore
{
Guid Id;
}
class LaundryChore : Chore
{
// PROBLEMATIC
List<Clothing> ManyClothing;   
}
class FoldingChore : Chore
{
Clothing SingleClothing;   
}
class Clothing
{
Guid Id;

// PROBLEMATIC
List<Chore> Chores;
}

我用鉴别器设置了TPH,一切都很好。如果ManyClothing字段在Chore类上,那么我可以执行以下操作:

builder.Entity<Clothing>().HasMany(clothing => clothing.Chores)
.WithMany(chore => chore.ManyClothing);

这正如预期的那样。

但由于ManyClothing字段在LaundryChore类上,我会得到上面的DNE错误。

我试着切换方向:

builder.Entity<LaundryChore>().HasMany(chore => clothing.ManyClothing)
.WithMany(clothing => clothing.Chores);

我得到一个选角错误:

无法将类型"System.Collections.Generic.List"隐式转换为"System.Collections.Generic.IEnumerable">

如果我更改为:

class Clothing
{
Guid Id;
List<LaundryChore> Chores;
}

然后我得到的错误是:

筛选器表达式。。。不能为实体类型"LaundryChore"指定。过滤器只能应用于根实体类型"Chore">

如有任何指导,我们将不胜感激-谢谢!

导航属性只能参与单个关系

它不是限制类型,而是关系限制。例如,如果您只有ChoreClothing类:

public class Chore
{
public int Id { get; set; }
public List<Clothing> ManyClothingToLaundry { get; set; }
public Clothing SingleClothingToFolding { get; set; }
}
public class Clothing
{
public int Id { get; set; }
public List<Chore> Chores { get; set; }
}

现在,你想在服装中添加一个和弦:

clothing.Chores.Add(chore);

这会给洗衣或折叠增添麻烦吗?EF Core在这种情况下不知道。

在您的特定情况下,EF Core可以从类型中检测关系,但没有实现此功能。

如果Clothing有两个不同的关系,那么Clothing需要两个导航属性:

public class Clothing
{
public int Id { get; set; }
public List<Chore> FoldingChores { get; set; }
public List<Chore> LaundryChores { get; set; }
public IEnumerable<Chore> Chores => FoldingChores.Union(LaundryChores);
}
...
protected override void OnModelCreating(ModelBuilder builder)
{
...
builder.Entity<Clothing>().Ignore(c => c.Chores);
builder.Entity<Clothing>()
.HasMany<LaundryChore>(nameof(Clothing.LaundryChores))
.WithMany(chore => chore.ManyClothing);
builder.Entity<Clothing>()
.HasMany<FoldingChore>(nameof(Clothing.FoldingChores))
.WithOne(chore => chore.SingleClothing);
}

例如,Clothing.FoldingChores是基本实体Chore的集合,但它可以直接是压轴类型FoldingChore的集合。带Clothing.LaundryChores:的Idem

public class Clothing
{
public int Id { get; set; }
public List<FoldingChore> FoldingChores { get; set; }
public List<LaundryChore> LaundryChores { get; set; }
public IEnumerable<Chore> Chores => FoldingChores.Cast<Chore>().Union(LaundryChores.Cast<Chore>());
}

最新更新