LINQ Получить полный список объектов, включающий только свойства, соответствующие определенному условию - PullRequest
0 голосов
/ 15 февраля 2020

У меня есть две модели:

    public class Seat
    {
        public int Id { get; set; }
        public ICollection<Reservation> Reservations { get; set; }
    //..
    }

    public class Reservation
    {
        public int Id { get; set; }
        public int SeatId { get; set; }
        public Seat Seat { get; set; }
        public DateTime DateTime { get; set; }
        //..
    }

Скажем, место имеет бронирование на каждый день недели. Я хочу сделать запрос, который занимает места и фильтрует резервирование мест на требуемый день. Я хочу показать места и показать, какие из них свободны / зарезервированы на день X. Способы, которыми я пытался добиться этого:

        var seats = _dbContext.Seats
             .Include(s => s.Reservations.Where(r => r.DateTime.Date == dateParam.Date));
        // InvalidOperationException: 'Lambda expression used 
        // inside Include is not valid.'

Образец

       var seats = _dbContext.Seats
             .Include(s => s.Reservations)
             .Where(r => r.Reservations.Any(r => r.DateTime.Date == dateParam.Date));   
        // Gets the seats which meet the condition. I want these, but also I want the free seats

Образец

        var seatsFiltered = _dbContext.Seats
             .Include(t => t.Reservations)
             .Where(r => r.Reservations.Any(r => r.DateTime.Date == dateParam.Date))
             .ToList();

        var seats = _dbContext.Seats
             .ToList()
             .Select(x => { x.Reservations = new List<Reservation>(); return x; })
             .Concat(seatsFiltered);
        // Not optimal since I obviously ToList twice
        // In the end I get an empty list

        return (ICollection<Seat>)seats;

РЕДАКТИРОВАТЬ: Добавить пример данных в соответствии с запросом:

Мест

Id|AreaId|
--|------|
 1|3     | 
 2|3     |
 3|3     |
 4|3     |
 5|3     |
 6|3     |
 7|3     |
 8|3     |

Бронирование

Id|SeatId|Name|Phone|DateTime           |
--|------|----|-----|-------------------|
 7|     1|    |     |2020-02-15 20:30:00|
 8|     1|    |     |2020-02-21 12:00:00|
 9|     1|    |     |2020-02-23 09:00:00|
10|     2|    |     |2020-02-15 20:30:00|
11|     2|    |     |2020-02-21 12:00:00|
12|     2|    |     |2020-02-23 09:00:00|
13|     4|    |     |2020-02-21 12:00:00|
15|     7|    |     |2020-02-15 20:30:00|
16|     7|    |     |2020-02-21 12:00:00|
17|     8|    |     |2020-02-21 12:00:00|
14|     8|    |     |2020-02-23 09:00:00|
18|     3|    |     |2020-02-15 20:30:00|
19|     3|    |     |2020-02-21 12:00:00|
20|     3|    |     |2020-02-23 09:00:00|

Когда я попробовал код Phong, я получил следующая ошибка:

System.InvalidOperationException: 'выражение LINQ' (GroupByShaperExpression: KeySelector: (r.SeatId), ElementSelector: (EntityShaperExpression: EntityType: резервирование False)). ToList () 'не может быть переведен. Либо переписать запрос в форме, которую можно перевести, либо явно переключиться на оценку клиента, вставив вызов либо AsEnumerable (), AsAsyncEnumerable (), ToList (), либо ToListAsyn c (). См. https://go.microsoft.com/fwlink/?linkid=2101038 для получения дополнительной информации. '

Ответы [ 2 ]

0 голосов
/ 16 февраля 2020

Решение Фонга может быть абсолютно верным и полезным, но так как я сам не мог понять и применить его, я использовал этот метод

var seats = _dbContext.Seats.ToList();
var reservations = _dbContext.Reservations.Where(r => r.DateTime.Day == dateTime.Day).ToList();

foreach (var seat in seats)
{
    seat.Reservations = reservations.Where(r => r.SeatId == seat.Id).ToList();
}

Я все еще верю, что есть еще одна строка LINQ, которая может сделать это без учета производительности .ToList() - для каждой коллекции, но я не мог понять это:)

0 голосов
/ 15 февраля 2020

Вы должны GroupBy(), как показано ниже.

var seatsFiltered = _dbContext.Reservations
                          .Where(r => r.DateTime.Date == dateParam.Date))
                          .GroupBy(r => r.SeatId)
                          .Select(g => new 
{
  SeatId = g.Key,
  ListOfReservations = g // No need to .ToList() here
}) .ToList();
...