1

我是@LINQ 的新手我正在尽力而为。我知道如何以一对一的关系拉动和加入这些表,但我一直在尝试用更好的方法来实现这一点:

  1. 一对一
  2. 一对多

但是现在我不知道如何从游戏表中的特定日期时间获取玩家和分数。我正在使用:.NET Framework 4.7.2Entity Framework 6.4.4,并使用Code First方法。

编辑:我通常在匹配的 Datetime timestamp上加入他们。

编辑#2:我的尝试: ....=> t ->是对此的一些输入function,下面是body

var data = (from game in db.Games
        join p in db.Players on game.Players equals p
        join s in db.Scores on p equals s.Player
        where 
        (
            game.timestamp.Hour == t.Hour &&
            game.timestamp.Minute == t.Minute &&
            game.timestamp.Second == t.Second
        )
        select new { s, p }).ToList<Object>();

编辑#3:试图把它变成List<Object>().

编辑#4:当我尝试循环数据时,在返回数据后,使用@Svyatoslav Danyliv 的答案中的查询示例,我得到了这个:

在此处输入图像描述

我的桌子:

using System;
using System.Collections.Generic;

namespace Sample
{
    ////////////////////////////////////////
    //
    // Game and Player have a one-to-many relationship
    // Scores and Player have a one-to-one relationship
    //
    
    public class Player
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int PlayerID { get; set; }

        [MaxLength(200)]
        public string Name { get; set; }
        
        [DataType(DataType.DateTime)]
        public DateTime Created { get; set; };
    }
    
    public class Scores
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int ScoreID { get; set; }
        
        public int Wins { get; set; } = 0;
        public int Lost { get; set; } = 0;
        public int TimesPlayed { get; set; } = 0;

        [Required]
        public virtual Player Player { get; set; }
        
        [DataType(DataType.DateTime)]
        public DateTime timestamp { get; set; };
    }
    
    public class Game
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int ID { get; set; }
        
        public DateTime timestamp { get; set; };
        
        public virtual ICollection<Player> Players { get; set; } = new List<Player>();
    }
}
4

2 回答 2

0

您似乎缺少从 Player 到 Score 的导航属性,这似乎也是一个奇怪的设计,因为我通常会假设玩家可以玩多个游戏,因此可能有多个分数。但是,如果您添加缺少的导航属性,那么应该可以:

var data = db.Games
  .Include(g=>g.Players)
  .Include(g=>g.Players.Select(p=>p.Scores)) // EF 6.x
  //.ThenInclude(p=>p.Scores) // EF Core
  .Where(g=>g.timestamp.Hour == t.Hour)
  .Where(g=>g.timestamp.Minute == t.Minute)
  .Where(g=>g.timestamp.Second == t.Second)
  .ToList();

使用 DbFunctions 或 EntityFunctions 可能有更好的方法来处理您的游戏时间戳,例如:Linq To Sql compare Time only

如果您希望将其展平,则使用 SelectMany 进行项目:

var data = db.Games
  .Include(g=>g.Players)
  .Include(g=>g.Players.Select(p=>p.Scores)) // EF 6.x
  //.ThenInclude(p=>p.Scores) // EF Core
  .Where(g=>g.timestamp.Hour == t.Hour)
  .Where(g=>g.timestamp.Minute == t.Minute)
  .Where(g=>g.timestamp.Second == t.Second)
  .SelectMany(g=>g.Players)
  .ToList();
于 2020-12-24T21:41:22.060 回答
0

类似的东西,但我认为你必须对分数应用适当的过滤器timestamp

var query = 
   from game in db.Games
   where 
   (
      game.timestamp.Hour == t.Hour &&
      game.timestamp.Minute == t.Minute &&
      game.timestamp.Second == t.Second
   )
   select new 
   { 
      Game = game,
      Players = game.Players.Select(p => new 
      {
         Player = p,
         Scores = db.Scores.Where(s = s.Player == p).ToArray()
      }).ToArray()
   }

var result = query.ToList();
于 2020-12-25T09:56:22.497 回答