如果联接表的一侧是表中每个层次结构设置的派生类,那么我在用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">
如有任何指导,我们将不胜感激-谢谢!
导航属性只能参与单个关系
它不是限制类型,而是关系限制。例如,如果您只有Chore
和Clothing
类:
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>());
}