ASP.NET MVC6 中的实体框架 7 多个外键到同一个表 [英] Entity framework 7 in ASP.NET MVC6 multiple foreign key to the same table

查看:15
本文介绍了ASP.NET MVC6 中的实体框架 7 多个外键到同一个表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有同样的问题,这里有一篇旧帖子,那里提供的解决方案在带有 EF7 的 MVC 6 中对我不起作用很简单

公共类匹配{[钥匙]公共 int MatchId { 获取;放;}公共日期时间游戏日 { 获取;放;}公共浮动 HomePoints { 获取;放;}公共浮动 GuestPoints { 得到;放;}公共 int HomeTeamId { 获取;放;}公共 int GuestTeamId { 获取;放;}[外键(HomeTeamId")][InverseProperty("HomeMatches")]公共虚拟团队 HomeTeam { get;放;}[外键(GuestTeamId")][InverseProperty("客场比赛")]公共虚拟团队 GuestTeam { get;放;}}公开课团队{公共 int TeamId { 获取;放;}公共字符串名称 { 获取;放;}公共虚拟 ICollection<Match>HomeMatches { 得到;放;}公共虚拟 ICollection<Match>客场比赛{得到;放;}}

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

<块引用>

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

解决方案

我在准备答案时详细分析了问题 我可以为您推荐两种解决问题的方法.

问题是因为Match

类中有两个属性

public int HomeTeamId { get;放;}公共 int GuestTeamId { 获取;放;}

以及将生成的外键 HomeTeamIdGuestTeamId.EF7 使用ON DELETE CASCADE 生成外键,不能作为一个外键使用多个.实体框架 (RC1) 的当前实现没有可用于更改行为的注释属性.

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

public int?HomeTeamId { 获取;放;}公众号?GuestTeamId { 获取;放;}

public int HomeTeamId { get;放;}公众号?GuestTeamId { 获取;放;}

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

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

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

公共类 MyDBContext : DbContext{DbSet<团队>团队{得到;放;}DbSet<Match>匹配 { 获取;放;}}

要解决描述问题,您可以在显式设置

的类中添加受保护的OnModelCreating

公共类 MyDBContext : DbContext{protected override void OnModelCreating(ModelBuilder modelbuilder){base.OnModelCreating(modelbuilder);modelbuilder.Entity(typeof (Match)).HasOne(typeof (Team), "GuestTeam").和很多().HasForeignKey("GuestTeamId").OnDelete(DeleteBehavior.Restrict);//没有删除modelbuilder.Entity(typeof (Match)).HasOne(typeof (Team), "HomeTeam").和很多().HasForeignKey("GuestTeamId").OnDelete(DeleteBehavior.Cascade);//设置 ON 删除级联}DbSet<团队>团队{得到;放;}DbSet<Match>匹配 { 获取;放;}}

您可以在两个外键上使用 DeleteBehavior.Restrict 原因(而不是在一个外键上使用 DeleteBehavior.Cascade).需要注意的是,最后一种方法允许将 HomeTeamIdGuestTeamId 都保存为不可为空,就像数据库中的相应字段一样.

有关其他信息,请参阅文档.>

Hi I have the same problem that an old post that is here, the solution offer there doesn't work for me in MVC 6 with EF7 is simple

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

this is the best way that I found, because I can add a new migration and all is ok, but when I update the database I get an error like this

Introducing FOREIGN KEY constraint 'FK_Match_Team_HomeTeamId' on table 'Match' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. Could not create constraint or index. See previous errors.

解决方案

I analysed the problem in details during preparing the answer and I can suggest you two solutions of the problem.

The problem exist because of two properties in the class Match

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

and the foreign keys HomeTeamId and GuestTeamId which will be generated. EF7 generate the foreign keys with ON DELETE CASCADE, which can't be used for more as one foreign key. The current implementation of Entity Framework (RC1) have no annotation attribute, which you can use to change the behavior.

The first solution of the problem would be to use nullable properties like

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

or

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

Maximum one property should be non nullable. As the result the problem will be solved, but one will have small disadvantage, which could be not important for some scenarios. The field in the database table for nullable property will have no NOT NULL property in the column definition.

If you do need to hold both HomeTeamId and GuestTeamId non-nullable then you can solve the problem by modifying the context class (inherited from DbContext), where the classes Match and Team be used.

You have already some context class defined line below

public class MyDBContext : DbContext
{
    DbSet<Team> Teams { get; set; }
    DbSet<Match> Matches { get; set; }
}

To solve the describe problem you can add protected OnModelCreating in the class which explicitly set

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

You can use of cause DeleteBehavior.Restrict on both foreign keys (instead of usage of DeleteBehavior.Cascade on one). It's important to remark that the last approach allows to hold both HomeTeamId and GuestTeamId, like the corresponding fields in the database, as non-nullable.

See the documentation for additional information.

这篇关于ASP.NET MVC6 中的实体框架 7 多个外键到同一个表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆