Я новичок в @ LINQ и стараюсь изо всех сил. Я знаю, как вытащить и соединить эти таблицы в отношениях один к одному, но я застрял, пытаясь реализовать это с помощью лучшего подхода:
Но теперь я понятия не имею, как получить Player и Scores, но с определенного Datetime в таблице Game. Я использую: .NET Framework 4.7.2 и Entity Framework 6.4.4 и работаю с подходом Code First.
Обновлено: я обычно присоединяюсь к ним по соответствующей метке времени Datetime.
РЕДАКТИРОВАТЬ № 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>();
}
}
Кажется, вам не хватает свойства навигации от игрока к счету, что также кажется странным дизайном, поскольку я обычно предполагаю, что игрок может играть в несколько игр и, следовательно, может иметь несколько очков. Однако, если вы добавите отсутствующее свойство навигации, оно должно работать:
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, сравнивайте только время
Если вы хотите, чтобы это было сглажено, спроектируйте с помощью 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();
Что-то вроде этого, но я думаю, что вы должны применить соответствующий фильтр к счету 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();
Выглядит круто, но я не могу заставить его работать List<Object>
Потому что я хочу зациклить каждый объект? А доступ как свойства, или так нельзя?
Исходный вопрос не содержит информации об этом. Обновлять. вопрос, и я проверю, возможно это или нет.
Обновлено сейчас. Может быть, теперь это яснее. Я только что попробовал, но я не уверен. Я получаю AnonymousType.
Я не понял из вашего обновления, для чего вам это нужно. Но перенос в List<Object> прост: query.AsEmumerable().Cast<object>().ToList()
Ну, я решил это. Совсем по-другому, и, кажется, работает отлично.
Привет, Роберт, этот дизайн предназначен для хранения только «исторических» записей, поэтому новые игроки могут играть. После игры все хранится. Не предназначено иметь отдельные учетные записи или что-то в этом роде. Только записи истории.