嗨我有同样的问题,这里有一个老帖子,解决方案提供的对我来说在MVC 6中使用EF7很简单
public class Match
{
[Key]
public int MatchId { get; set; }
public DateTime playday { get; set; }
public float HomePoints { get; set; }
public float GuestPoints { get; set; }
public int HomeTeamId { get; set; }
public int GuestTeamId { get; set; }
[ForeignKey("HomeTeamId")]
[InverseProperty("HomeMatches")]
public virtual Team HomeTeam { get; set; }
[ForeignKey("GuestTeamId")]
[InverseProperty("AwayMatches")]
public virtual Team GuestTeam { get; set; }
}
public class Team
{
public int TeamId { get; set; }
public String name { get; set; }
public virtual ICollection<Match> HomeMatches { get; set; }
public virtual ICollection<Match> AwayMatches { get; set; }
}
这是我找到的最佳方式,因为我可以添加新的迁移,一切正常,但是当我更新数据库时,我收到这样的错误
在表'匹配'上引入FOREIGN KEY约束'FK_Match_Team_HomeTeamId'可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束。 无法创建约束或索引。查看以前的错误。
答案 0 :(得分:4)
我在准备the answer时详细分析了问题,我建议你解决问题的两个方法。
由于类Match
public int HomeTeamId { get; set; }
public int GuestTeamId { get; set; }
以及将生成的外键HomeTeamId
和GuestTeamId
。 EF7使用ON DELETE CASCADE
生成外键,不能将其用作一个外键。实体框架(RC1)的当前实现没有注释属性,您可以使用它来更改行为。
问题的第一个解决方案是使用像
这样的可空属性public int? HomeTeamId { get; set; }
public int? GuestTeamId { get; set; }
或
public int HomeTeamId { get; set; }
public int? GuestTeamId { get; set; }
最多一个属性应该是不可为空的。结果问题将得到解决,但是会有一个小缺点,这对某些情况可能并不重要。 nullable属性的数据库表中的字段在列定义中没有NOT NULL
属性。
如果确实需要同时保持HomeTeamId
和GuestTeamId
不可空,那么您可以通过修改上下文类(继承自DbContext)来解决问题,其中类Match
和Team
可以使用。
您已经在下面定义了一些上下文类
public class MyDBContext : DbContext
{
DbSet<Team> Teams { get; set; }
DbSet<Match> Matches { get; set; }
}
要解决描述问题,您可以在明确设置
的类中添加受保护的OnModelCreating
public class MyDBContext : DbContext
{
protected override void OnModelCreating(ModelBuilder modelbuilder)
{
base.OnModelCreating(modelbuilder);
modelbuilder.Entity(typeof (Match))
.HasOne(typeof (Team), "GuestTeam")
.WithMany()
.HasForeignKey("GuestTeamId")
.OnDelete(DeleteBehavior.Restrict); // no ON DELETE
modelbuilder.Entity(typeof (Match))
.HasOne(typeof (Team), "HomeTeam")
.WithMany()
.HasForeignKey("GuestTeamId")
.OnDelete(DeleteBehavior.Cascade); // set ON DELETE CASCADE
}
DbSet<Team> Teams { get; set; }
DbSet<Match> Matches { get; set; }
}
您可以在两个外键上使用原因DeleteBehavior.Restrict
(而不是在一个外键上使用DeleteBehavior.Cascade
)。重要的是要注意,最后一种方法允许将HomeTeamId
和GuestTeamId
与数据库中的相应字段一样保持为不可为空。
有关其他信息,请参阅the documentation。
答案 1 :(得分:0)
如果您愿意,可以使用级联删除手动在数据库上创建此FK,并检查您为什么要使用此循环级联循环。要了解我们需要其他表或涉及的数据库结构。请检查您的数据库(例如图表),绘制您的连接表,您的FK以及每个研究您计划的操作(级联删除,无操作,......)及其方向。当你试图错误地插入那个FK时,你会找到一个循环。
下一阶段是要了解您是否需要它,是否是一个不需要的数据库设计?或者只是你不需要这个FK行动?在这种情况下,您可以在各种级别禁止它:在模型,设置,...其他帖子或EF指南。