基于多对多EF关系构建二维表

时间:2015-03-10 23:43:55

标签: c# asp.net-mvc entity-framework

我想基于Driver / Race / Points关系建立一个二维表。

型号:

public class Race
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime RaceStart { get; set; }
    public Circuit Circuit { get; set; }
    public virtual ICollection<DriverRacePoint> DriverRacePoints { get; set; }
}

public class Driver
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public int Standing { get; set; }
    public virtual ICollection<DriverRacePoint> DriverRacePoints { get; set; }
}

public class DriverRacePoint
{
    [Key, Column("Driver_Id", Order = 0)]
    public int Driver_Id { get; set; }

    [Key, Column("Race_Id", Order = 1)]
    public int Race_Id { get; set; }

    [ForeignKey("Driver_Id")]
    public virtual Driver Driver { get; set; }

    [ForeignKey("Race_Id")]
    public virtual Race Race { get; set; }

    public string Points { get; set; }
}

结果视图:

        |   Race1   |   Race2   |   Race3   |   Race4  |
Driver1 |  points   |   points  |   points  |  points   | total points
Driver2 |  points   |   points  |   points  |  points   | total points  
Driver3 |  points   |   points  |   points  |  points   | total points  

行顺序不是总数,而是Driver.Standing

如何从DbContext构建ViewModel以获取结果视图?

以下是我需要的结果示例:

http://en.espnf1.com/f1/motorsport/season/138549.html?template=standings

1 个答案:

答案 0 :(得分:1)

我不明白为什么Points实体中的DriverRacePoint属性为string,但如果您为数字类型更改了该属性,例如{{1} },你可以这样做以获得你需要的信息:

int

更新1

如果您需要驱动程序信息,则可以通过以下方式修改查询:

 using (var db = new YourDbContext())
 {
   var query = (from driver in db.Drivers
                join drp in db.DriverRacePoints on driver.Id equals drp.Driver_Id
                join race in db.Races on drp.Race_Id equals race.Id
                where race.RaceStart.Year==2014 //races for an specific year
                group new {driver,drp, race} by driver.Id into g
                select new {DriverId=g.Key,// The driver Id
                            RacesWithPoints=g.Select(a=>new {a.race,a.drp.Points}),// All the races ( and the points X race) where the driver participates
                            TotalPoints=g.Sum(a=>a.drp.Points)// Total of points
                           }).OrderByDescending(e=>e.TotalPoints);
   //use the data that you get from this query
 }
  

对于标题中的种族列表,我建议如何构建它?

嗯,问题是你不知道是否有一些司机参与了所有的比赛。所以我认为你需要再做一次查询:

    var query = (from driver in db.Drivers
                join drp in db.DriverRacePoints on driver.Id equals drp.Driver_Id
                join race in db.Races on drp.Race_Id equals race.Id
                where race.RaceStart.Year==2014 //races for an specific year
                group new {driver,drp, race} by driver.Id into g
                select new {    DriverName = g.FirstOrDefault().driver.Name,
                                DriverUrlSlug = g.FirstOrDefault().driver.UrlSlug,
                                // All the races ( and the points X race) where the driver participates
                                RacesWithPoints = g.Select(a => new StandingRacePointsVM { RacePoints = a.drp.Points == null ? -1 : a.drp.Points }).ToList(),
                                TotalPoints = g.Sum(a => a.drp.Points),
                                Standing = g.FirstOrDefault().driver.Standing
                            }).OrderBy(d => d.Standing).ToList();

更新2

我认为此查询对您更好,但我无法对其进行测试,因为我没有您的模型和数据。此查询将为您提供所有驱动程序,对于每个驱动程序,您将获得所有比赛的列表,包括他未参与的位置:

  var query2 = from race in db.Races
                where race.RaceStart.Year == 2014
                select new {race.Id, race.Name};

现在要创建标题,您可以使用 var query3 = (from driver in db.Drivers join drp in db.DriverRacePoints on driver.Id equals drp.Driver_Id from race in db.Races where race.RaceStart.Year == 2014 select new { driver,drp, race }) .GroupBy(e => e.driver.Id) .Select(g => new { DriverName = g.FirstOrDefault().driver.Name, RacesWithPoints = g.Select(a => new { a.race.Name, Points = a.drp.Race_Id == a.race.Id ? 0 : a.drp.Points }), // All the races (if the driver was involved => you have the Points value, otherwise, the value is 0 ) TotalPoints = g.Sum(a => a.drp.Points)// Total of points }).OrderByDescending(e=>e.TotalPoints); 选择第一个用于迭代foreach比赛的驱动程序。