Запрос Linq2Entities для поиска записей по заданному диапазону mix-max - PullRequest
0 голосов
/ 02 июня 2019

У меня есть эти две сущности:

public class Ticket
{
    public int Id { get; set; }
    public int ScheduleId { get; set; }
    public int SeatId { get; set; }

    [DataType(DataType.Date)]
    [Column(TypeName = "Date")]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    public DateTime ForDate { get; set; }

    public Seat Seat { get; set; }
    public Schedule Schedule { get; set; }
    public ICollection<TicketStop> TicketStops { get; set; }
}

public class TicketStop
{
    public int Id { get; set; }
    public int TicketId { get; set; }
    public int LineStopStationId { get; set; }

    public Ticket Ticket { get; set; }
    public LineStopStation LineStopStation { get; set; }
}

public class LineStopStation
{
    public int Id { get; set; }
    public int LineId { get; set; }
    public int StopId { get; set; }
    public int Order { get; set; }
    public bool IsLastStop { get; set; }

    public Line Line { get; set; }
    public Stop Stop { get; set; }
}

Экономический пример заключается в том, что я внедряю систему бронирования билетов на автобусы (в основном для учебных целей) и хочу найти перекрывающиеся билеты.

Комбинация LineId + ScheduleId + ForDate однозначно определяет, что это билет на определенный автобус на определенную дату и время отправления.

Проблема, с которой я столкнулся, заключается в том, чтобы определить с учетом начального и конечного местоположения, перекрываются ли два билета на одну или несколько остановок.

Сущность LineStopStation содержит информацию о StopId иOrder, в котором он посещается во время поездки на автобусе.Таким образом, в основном перекрывающиеся билеты будут иметь один и тот же номер Order в какой-то момент (если это не последняя остановка, что означает, что пассажир покидает автобус).

Итак, у меня есть LineId, ScheduleId, StartId и EndId, где starId и endId соответствуют LineStopStation.StopId, поэтому в конечном итоге я смогу получить из них Орден следующим образом.

        int startStationOrder = _context.LineStopStations
            .First(l => l.LineId == lineId && l.StopId == startId).Order;

        int endStationOrder = _context.LineStopStations
            .First(l => l.LineId == lineId && l.StopId == endId).Order;

Так что я вполне уверен, что имеявсю эту информацию я смогу найти, если в таблице TicketStop есть билет, который пересекается с данными.TicketStop работает следующим образом - если кто-то купил билет на 3 остановки, у меня там будет три записи с одинаковыми TicketId и тремя разными LineStopStationId.

Я чувствую, что этот вопрос стал больше, чем нужно,Так что в основном у меня есть это:

 public List<Seat> GetAvailableSeats(int lineId, int scheduleId, int startId, int endId, DateTime forDate)
 {
   int startStationOrder = _context.LineStopStations
       .First(l => l.LineId == lineId && l.StopId == startId).Order;

   int endStationOrder = _context.LineStopStations
       .First(l => l.LineId == lineId && l.StopId == endId).Order;

   var reservedSeats = _context.TicketStops
       .Where(t => t.Ticket.ScheduleId == scheduleId)
       .Where(t => t.Ticket.ForDate == forDate)
       //basically I don't know how to proceed here.
       //In pseudo code it should be something like:
       .Where(t => t.Min(Order) >= endStationOrder || t.Max(Order) <= startStationOrder

 }

Но обс.это не то, как LINQ работает.Так, как я могу найти все билеты, где этот диапазон перекрывается?

1 Ответ

1 голос
/ 03 июня 2019

Без глубокого анализа вашей модели, возможно, что-то подобное может дать вам представление?

var reservedSeats = _context.TicketStops
                            .GroupBy(t => new { t.Ticket.ScheduleId, t.Ticket.ForDate })
                            .Where(tg => tg.Key == new { ScheduleId = scheduleId, ForDate = forDate })
                            .Where(tg => tg.Min(t => t.LineStopStation.Order) >= endStationOrder || tg.Max(t => t.LineStopStation.Order) <= startStationOrder);

Вы также можете сначала отфильтровать и сделать пустое GroupBy:

var reservedSeats = _context.TicketStops
                            .Where(t => t.Ticket.ScheduleId == scheduleId && t.Ticket.ForDate == forDate)
                            .GroupBy(t => 1)
                            .Where(tg => tg.Min(t => t.LineStopStation.Order) >= endStationOrder || tg.Max(t => t.LineStopStation.Order) <= startStationOrder);

Чтобы вернуть все SeatId s, вам просто нужно выбрать их из группы.

var reservedSeats = _context.TicketStops
                            .Where(t => t.Ticket.ScheduleId == scheduleId && t.Ticket.ForDate == forDate)
                            .GroupBy(t => 1)
                            .Where(tg => tg.Min(t => t.LineStopStation.Order) >= endStationOrder || tg.Max(t => t.LineStopStation.Order) <= startStationOrder);
                            .SelectMany(tg => tg.Select(t => t.Ticket.SeatId));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...