C# EF Core中跟踪赛车结果的数据库结构

C# EF Core中跟踪赛车结果的数据库结构,c#,asp.net-mvc,entity-framework,model-view-controller,asp.net-core,C#,Asp.net Mvc,Entity Framework,Model View Controller,Asp.net Core,作为学习新知识的一种方式,我决定尝试创建一个网站,在C#.Net Core MVC中跟踪赛车成绩,并使用EF创建代码优先数据库 然而,一开始我就想知道,我的数据结构采用了错误的方法 我有国家和季节的模型,它们是简单的(ID、名称,对于季节,还有一系列的比赛)。然而,我做赛车和车手模型的方式有点复杂。我想追踪a)比赛在哪里,b)比赛是哪个赛季的一部分,c)哪个车手在哪里完成比赛 每场比赛将有26名车手参加 以下是我为race创建的模型: public class Race {

作为学习新知识的一种方式,我决定尝试创建一个网站,在C#.Net Core MVC中跟踪赛车成绩,并使用EF创建代码优先数据库

然而,一开始我就想知道,我的数据结构采用了错误的方法

我有国家和季节的模型,它们是简单的(ID、名称,对于季节,还有一系列的比赛)。然而,我做赛车和车手模型的方式有点复杂。我想追踪a)比赛在哪里,b)比赛是哪个赛季的一部分,c)哪个车手在哪里完成比赛

每场比赛将有26名车手参加

以下是我为race创建的模型:

    public class Race
    {
        public int ID { get; set; }
        public int SeasonID { get; set; }
        public Season Season { get; set; }
        public int NationID { get; set; }
        public Nation Nation { get; set; }

        public int Driver1ID { get; set; }
        [ForeignKey("Driver1ID")]
        public virtual Driver Driver1 { get; set; }

        public int Driver2ID { get; set; }
        [ForeignKey("Driver2ID")]
        public virtual Driver Driver2 { get; set; }

        public int Driver3ID { get; set; }
        [ForeignKey("Driver3ID")]
        public virtual Driver Driver3 { get; set; }

        // And so on, I'll spare you the rest, it goes all the way down to 26...

        public int Driver26ID { get; set; }
        [ForeignKey("Driver26ID")]
        public virtual Driver Driver26 { get; set; }


    }
以下是驾驶员的模型:

public class Driver
    {
        public int ID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int NationID { get; set; }
        public Nation Nation { get; set; }
        public ICollection<Race> P1 { get; set; }
        public ICollection<Race> P2 { get; set; }
        public ICollection<Race> P3 { get; set; }
// Again I'll save you the whole thing, it goes down to 26...
        public ICollection<Race> P26 { get; set; }
    }
公共类驱动程序
{
公共int ID{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
public int NationID{get;set;}
公共国家{get;set;}
公共ICollection P1{get;set;}
公共ICollection P2{get;set;}
公共ICollection P3{get;set;}
//再说一次,我会把整件事都给你省下来,一共26件。。。
公共ICollection P26{get;set;}
}
为了实现这一点,我想我必须像这样在上下文类中设置关系

protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Race>().HasOne(r => r.Driver1).WithMany(d => d.P1);
            modelBuilder.Entity<Race>().HasOne(r => r.Driver2).WithMany(d => d.P2);
            modelBuilder.Entity<Race>().HasOne(r => r.Driver3).WithMany(d => d.P3);
// Snip down to 26 again...
            modelBuilder.Entity<Race>().HasOne(r => r.Driver26).WithMany(d => d.P26);
        }
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
modelBuilder.Entity().HasOne(r=>r.Driver1).WithMany(d=>d.P1);
modelBuilder.Entity().HasOne(r=>r.Driver2).WithMany(d=>d.P2);
modelBuilder.Entity().HasOne(r=>r.Driver3).WithMany(d=>d.P3);
//再减到26分。。。
modelBuilder.Entity().HasOne(r=>r.Driver26).WithMany(d=>d.P26);
}
但是当我尝试更新数据库时,我得到一个错误,即这种结构会导致“循环或多个级联路径”,这听起来真的不太好。我知道可以关闭Cascade Delete,但是错误消息让我觉得我首先走错了路。。。我是不是找错人了


任何帮助或建议都将不胜感激

我想我会用这样的方式来建模(不考虑季节、国家等因素):

公共级比赛
{
公共int ID{get;set;}
公共虚拟ICollection参与者{get;set;}
}
公务舱司机
{
公共int ID{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共ICollection竞赛{get;set;}
}
公开课比赛参与
{
公共int ID{get;set;}
公共竞赛竞赛{get;set;}
公共驱动程序{get;set;}
//可能是这样的信息:
公共int起始位置{get;set;}
公共int FinalPosition{get;set;}
}

事实上,每场比赛都有26名参赛者,IMO应该是您业务逻辑的一部分,而不是数据库设计的一部分。这可能是将来某个时候会发生变化的事情(即,当您希望每场比赛有不同数量的参赛者时)。因此,在代码中使用这种逻辑似乎更为灵活。

我想我会对其进行类似的建模(不考虑季节、国家等因素):

公共级比赛
{
公共int ID{get;set;}
公共虚拟ICollection参与者{get;set;}
}
公务舱司机
{
公共int ID{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共ICollection竞赛{get;set;}
}
公开课比赛参与
{
公共int ID{get;set;}
公共竞赛竞赛{get;set;}
公共驱动程序{get;set;}
//可能是这样的信息:
公共int起始位置{get;set;}
公共int FinalPosition{get;set;}
}

事实上,每场比赛都有26名参赛者,IMO应该是您业务逻辑的一部分,而不是数据库设计的一部分。这可能是将来某个时候会发生变化的事情(即,当您希望每场比赛有不同数量的参赛者时)。因此,在代码中使用这种逻辑似乎更灵活。

您不应该有26个单独的导航属性。只需使用Race和Driver之间的多对多关系,可能使用一个称为RaceParticipant之类的显式链接实体。您不应该有26个单独的导航属性。只需使用Race和Driver之间的多对多关系,可能使用一个显式链接实体,称为RaceParticipant之类的东西。
public class Race
{
    public int ID { get; set; }

    public virtual ICollection<RaceParticipation> Participants { get; set; }
 }

public class Driver
{
    public int ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public ICollection<RaceParticipation> Races { get; set; }
}

public class RaceParticipation
{
    public int ID {get;set;}
    public Race Race {get;set;}
    public Driver Driver {get;set;}
    // maybe information like this:
    public int StartingPosition {get;set;}
    public int FinalPosition {get;set;}
}