Построить запросы в LINQ-to-Entities в Entity Framework ASP. NET MVC - PullRequest
0 голосов
/ 22 февраля 2020

Мне трудно создать запрос LINQ-to-Entities, который бы удовлетворял моим требованиям.

У меня есть две таблицы: Бронирование и ProcessStatusLog

Таблица бронирования:

  • PNNumber (PK)
  • AccountName

ProcessStatusLog Таблица:

  • ID (PK)
  • PNNumber (FK)
  • InsuranceCode
  • Статус
  • ОбновленоOn

Вот пример данных для этих таблиц:

Таблица бронирования

|----------|----------------|
| PNNumber | Account Name   |
|----------|----------------|
| 11111    | Boston Celtics |
|----------|----------------|
| 22222    | Miami Heat     |
|----------|----------------|

Таблица ProcessStatusLog

|------|-----------|---------------|--------------|-------------|
| ID   | PNNumber  | InsuranceCode | Status       | UpdatedOn   |
|------|-----------|---------------|--------------|-------------|
| 1    | 11111     | FIRE          | NEW          | 02/22/2020  |
|------|-----------|---------------|--------------|-------------|
| 2    | 11111     | FIRE          | FOR REVIEW   | 02/23/2020  |
|------|-----------|---------------|--------------|-------------|
| 3    | 22222     | FIRE          | NEW          | 02/24/2020  |
|------|-----------|---------------|--------------|-------------|
| 4    | 22222     | MORTGAGE      | NEW          | 02/25/2020  |
|------|-----------|---------------|--------------|-------------|
| 5    | 22222     | MORTGAGE      | FOR REVIEW   | 02/26/2020  |
|------|-----------|---------------|--------------|-------------|
| 6    | 22222     | FIRE          | CANCELLED    | 02/28/2020  |
|------|-----------|---------------|--------------|-------------|

Теперь я хочу получить последнюю версию статус для одного PN для страхового кода.

Например: я хочу получить самый последний статус для номера PNN 11111. Я хочу получить вывод "FOR REVIEW".

А для PNNumber 22222 необходим вывод: "ДЛЯ ОБЗОРА, ОТМЕНЕНО"

Как я могу написать запрос EF для этого? Спасибо.

Ответы [ 2 ]

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

Повторно созданная база данных:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Booking>().HasKey(b => b.PNNumber);
    modelBuilder.Entity<Booking>().HasData(
        new Booking { PNNumber = "11111", AccountName = "Boston Celtics" },
        new Booking { PNNumber = "22222", AccountName = "Miami Heat" });

    modelBuilder.Entity<ProcessStatusLog>().HasData(
        new ProcessStatusLog { ID = 1, PNNumber = "11111", InsuranceCode = "FIRE", Status = "NEW", UpdatedOn = DateTime.Parse("22/02/2020") },
        new ProcessStatusLog { ID = 2, PNNumber = "11111", InsuranceCode = "FIRE", Status = "FOR REVIEW", UpdatedOn = DateTime.Parse("23/02/2020") },
        new ProcessStatusLog { ID = 3, PNNumber = "22222", InsuranceCode = "FIRE", Status = "NEW", UpdatedOn = DateTime.Parse("24/02/2020") },
        new ProcessStatusLog { ID = 4, PNNumber = "22222", InsuranceCode = "MORTGAGE", Status = "NEW", UpdatedOn = DateTime.Parse("25/02/2020") },
        new ProcessStatusLog { ID = 5, PNNumber = "22222", InsuranceCode = "MORTGAGE", Status = "FOR REVIEW", UpdatedOn = DateTime.Parse("26/02/2020") },
        new ProcessStatusLog { ID = 6, PNNumber = "22222", InsuranceCode = "FIRE", Status = "CANCELLED", UpdatedOn = DateTime.Parse("28/02/2020") });

    base.OnModelCreating(modelBuilder);
}

Запрос:

public IActionResult Index()
{
    this.dbContext.Database.EnsureCreated();

    string givenPNNumber = "22222";

    var filteredLogs = dbContext.ProcessStatusLog
        .Where(log => log.PNNumber == givenPNNumber);

    // Get date of the latest log for each incurance code for eaxh PNNumber.
    var groupedLogs = filteredLogs
        .GroupBy(psl => psl.InsuranceCode)
        .Select(group => new
        {
            Code = group.Key,
            LastUpdate = group.Max(g => g.UpdatedOn)
        });

    var result =
        from logs in filteredLogs
        join latestLogs in groupedLogs 
            on logs.InsuranceCode equals latestLogs.Code into joined
        from j in joined.DefaultIfEmpty()
        where logs.UpdatedOn == j.LastUpdate
        select logs.Status;

    string finalResult = string.Join(',', result.ToList());
    return View();
}

Поскольку я использовал только БД в памяти, я не знаю, как EF сгенерирует запрос, но план для запроса:

  • получить список журналов только для данного PNNumber,
  • из этого отфильтрованного списка получить список InsuranceCode s для данного PNNumber вместе с самой новой датой любого журнала для этого PNNumber и InsuranceCode
  • присоединяются к результатам (список InsuranceCode, UpdatedOn, Max(UpdatedOn)
  • из этого объединить выберите только те строки, в которых UpdatedOn == Max(UpdatedOn) (последние сущности для всех InsuranceCode с для данного PNNumber)
  • выберите Status es
  • присоединиться к ним.
0 голосов
/ 22 февраля 2020

Я не знаю, будет ли он напрямую переведен в SQL или вам нужно будет сначала получить весь список, но вы должны быть в состоянии достичь этого с помощью метода [GroupBy][1].

Предполагая, что ваша Booking модель имеет список ProcessStatusLog объектов с именем ProcessStatusLogs, она должна выглядеть примерно так:

var result = bookings.GroupBy(
  x => x.Id,
  (_, g) => g.SelectMany(x => x.ProcessStatusLogs)
             .OrderByDescending(x => x.UpdatedOn)
             .FirstOrDefault()
);
...