Ice*_*urn 6 entity-framework-core asp.net-core
我有一个Ticket实体:
public class Ticket
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<Relation> RelatedTickets { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我想在Entity Framework Core中设置多对多自相关,因此我建立了两个一对多关系:
public class Relation
{
[Required, ForeignKey("TicketFrom")]
public int FromId { get; set; }
[Required, ForeignKey("TicketTo")]
public int ToId { get; set; }
public virtual Ticket TicketFrom { get; set; }
public virtual Ticket TicketTo { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我尝试使用流畅的API创建关系:
builder.Entity<Relation>()
.HasKey(uc => new { uc.FromId, uc.ToId });
builder.Entity<Relation>()
.HasOne(c => c.TicketFrom)
.WithMany(p => p.RelatedTickets)
.HasForeignKey(pc => pc.FromId);
builder.Entity<Relation>()
.HasOne(c => c.TicketTo)
.WithMany(p => p.RelatedTickets)
.HasForeignKey(pc => pc.ToId);
Run Code Online (Sandbox Code Playgroud)
但结果我有一个错误:
无法在“ Ticket.RelatedTickets”和“ Relation.TicketTo”之间创建关系,因为“ Ticket.RelatedTickets”和“ Relation.TicketForm”之间已经存在关系。导航属性只能参与单个关系。
可能的解决方案是直接将Parent关系添加到TicketEntity:
public class Ticket
{
public int Id { get; set; }
[Required, ForeignKey("ParentRelation")]
public Nullable<int> ParentRelationId { get; set; }
public virtual Ticket ParentRelation {get;set;}
public virtual ICollection<Ticket> RelatedTickets { get; set; }
...
}
Run Code Online (Sandbox Code Playgroud)
使用像这样的流利的api:
modelBuilder.Entity<Ticket> =>
{
entity
.HasMany(e => e.RelatedTickets)
.WithOne(e => e.ParentRelation)
.HasForeignKey(e => e.ParentRelationId );
});
Run Code Online (Sandbox Code Playgroud)
但是这样存储父级关系看起来“肮脏”。
什么是正确的方法?
不可能只有一个具有关系的集合。您需要两个,一个与票证相等的TicketFrom关系,第二个与票证相等的关系TicketTo。
像这样:
模型:
public class Ticket
{
public int Id { get; set; }
public string Title { get; set; }
public virtual ICollection<Relation> RelatedTo { get; set; }
public virtual ICollection<Relation> RelatedFrom { get; set; }
}
public class Relation
{
public int FromId { get; set; }
public int ToId { get; set; }
public virtual Ticket TicketFrom { get; set; }
public virtual Ticket TicketTo { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
组态:
modelBuilder.Entity<Relation>()
.HasKey(e => new { e.FromId, e.ToId });
modelBuilder.Entity<Relation>()
.HasOne(e => e.TicketFrom)
.WithMany(e => e.RelatedTo)
.HasForeignKey(e => e.FromId);
modelBuilder.Entity<Relation>()
.HasOne(e => e.TicketTo)
.WithMany(e => e.RelatedFrom)
.HasForeignKey(e => e.ToId);
Run Code Online (Sandbox Code Playgroud)
请注意,使用Parent的解决方案并不等效,因为它会创建one-to-many关联,而如果我理解正确,那么您正在寻找many-to-many。
这里很好地解释了如何在 EF Core 多对多自引用关系中建立多对多关系
每个集合或引用导航属性只能是单个关系的一部分。而具有显式连接实体的多对多关系是通过两个一对多关系实现的。连接实体包含两个引用导航属性,但主实体只有一个集合导航属性,必须与其中之一相关联,但不能同时与两者相关联。
builder.Entity<Relation>()
.HasKey(uc => new { uc.FromId, uc.ToId });
builder.Entity<Relation>()
.HasOne(c => c.TicketFrom)
.WithMany() // <-- one of this must be empty
.HasForeignKey(pc => pc.FromId)
.OnDelete(DeleteBehavior.Restrict);
builder.Entity<Relation>()
.HasOne(c => c.TicketTo)
.WithMany(p => p.RelatedTickets)
.HasForeignKey(pc => pc.ToId);
Run Code Online (Sandbox Code Playgroud)
只需确保 WithMany 与相应导航属性的存在/不存在完全匹配。
请注意,您必须关闭删除级联。
| 归档时间: |
|
| 查看次数: |
2694 次 |
| 最近记录: |