【问题标题】:Entity framework 7 in ASP.NET MVC6 multiple foreign key to the same tableASP.NET MVC6中的实体框架7对同一个表的多个外键
【发布时间】:2016-05-07 23:54:08
【问题描述】:

您好,我的问题与此处的旧帖子相同,在带有 EF7 的 MVC 6 中提供的解决方案对我不起作用很简单

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; }
}

这是我找到的最好的方法,因为我可以添加一个新的迁移并且一切正常,但是当我更新数据库时,我会收到这样的错误

在表“Match”上引入 FOREIGN KEY 约束“FK_Match_Team_HomeTeamId”可能会导致循环或多个级联路径。指定 ON DELETE NO ACTION 或 ON UPDATE NO ACTION,或修改其他 FOREIGN KEY 约束。 无法创建约束或索引。查看以前的错误。

【问题讨论】:

  • 如果您将问题附加到上下文类的定义中(继承自 DbContext),这将很重要,其中使用了 MatchTeam。可以在上下文类中进行一些更改来解决问题。

标签: asp.net-mvc entity-framework entity-framework-core


【解决方案1】:

我在准备the answer时详细分析了这个问题,我可以建议你解决这个问题的两种方法。

由于类Match中的两个属性而存在问题

public int HomeTeamId { get; set; }
public int GuestTeamId { get; set; }

以及将生成的外键HomeTeamIdGuestTeamId。 EF7用ON DELETE CASCADE生成外键,不能作为一个外键多用。 Entity Framework (RC1) 的当前实现没有注释属性,您可以使用它来更改行为。

问题的第一个解决方案是使用可以为空的属性,例如

public int? HomeTeamId { get; set; }
public int? GuestTeamId { get; set; }

public int HomeTeamId { get; set; }
public int? GuestTeamId { get; set; }

最多一个属性不能为空。结果问题将得到解决,但会有一个小缺点,这对于某些场景可能并不重要。可空属性的数据库表中的字段在列定义中将没有NOT NULL 属性。

如果您确实需要同时保持HomeTeamIdGuestTeamId 不可为空,那么您可以通过修改上下文类(继承自DbContext)来解决问题,其中使用了MatchTeam 类。

你已经在下面定义了一些上下文类

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)。需要注意的是,最后一种方法允许将HomeTeamIdGuestTeamId 与数据库中的相应字段一样保持为不可为空。

更多信息请参见the documentation

【讨论】:

  • 你所说的对我帮助很大,因为我可以更好地理解问题但仍然无法为我工作,可为空的 int 不起作用,对我来说,我运行时仍然有同样的错误dnx ef 数据库更新命令,第二种方法看起来是最好的方法,但是当我运行更新时出现此错误实体类型“WebApplication1.Models.Match”上的导航“GuestTeam”尚未添加到模型中,或被忽略, 或忽略目标 entityType。
  • @DennisGonzalez:我确信你在这两种情况下都犯了小错误。您可以在某处提供完整的演示项目(例如在 GitHub 上,免费提供)。如果我可以重现问题,我可以快速找到原因并修复它。顺便说一句,在我看来,您以错误的方式使用 InverseProperty 属性。尝试删除它。
  • 我会尽快将这个项目放在 github 上,但我没有提交并提取所有更改,因为我尝试了我在互联网上找到的所有可能的解决方案,但没有任何效果,所以当我回家我会上传一个包含你所说的所有内容的新项目,如果你更喜欢这是 github 上的 previos 版本,没有你告诉我的github.com/Crash1988/SmartMove/tree/master/SmartMove
  • @DennisGonzalez:通常git push origin 应该可以工作。如果您在 Windows 下工作,那么GitHub Desktop 是支持 GitHub 存储库的最简单方法。我永久使用它。更先进,但更强制使用我可以推荐的客户端是SourceTree。您的存储库中 SmartMove 上的代码似乎不是最新的。我看到您在代码“个人用户帐户”中使用。是必需的吗?我建议在开头使用“无身份验证”或“Windows 身份验证”。
  • @DennisGonzalez:试试the project,我删除了许多不需要的部分。您可以构建项目,然后在项目目录中启动命令提示符并执行创建迁移的dnx ef migrations add Initial(或dnx ef migrations add Initial -v -c MyDBContext)。之后,您可以使用创建的迁移构建项目并执行dnx ef database update -v。之后,您可以使用该项目。您的问题似乎是因为您尝试将个人用户帐户数据库用于自定义数据。
【解决方案2】:

如果您愿意,您可以在数据库上手动创建此 FK 并使用级联删除,并检查您为什么要使用此循环级联循环。要了解我们需要其他表或所涉及的数据库结构。请检查您的数据库(例如使用图表),画出您的连接表、FK 和每个研究您计划的操作(级联删除、无操作......)和它们的方向。当您尝试错误地插入该 FK 时,您会填充 find 循环。

下一个阶段是了解您是否愿意,是否是不需要的数据库设计?或者只是你不需要这个 FK 动作?在这种情况下,您可以在各个级别上抑制它:在模型上、在设置上、...参见其他帖子或 EF 指南。

【讨论】:

    猜你喜欢
    • 2015-03-17
    • 1970-01-01
    • 1970-01-01
    • 2013-11-20
    • 1970-01-01
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多