在实体框架ASP.NET MVC中的LINQ到实体中构造查询

问题描述 投票:0回答:2

我很难创建满足我要求的LINQ-to-Entities查询。

我有两个表:BookingProcessStatusLog

预订表:

  • PNNumber(PK)
  • 帐户名

ProcessStatusLog表:

  • ID(PK)
  • PNNumber(FK)
  • 保险码
  • 状态
  • UpdatedOn

以下是这些表的示例数据:

预订桌

|----------|----------------|
| 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的最新状态。

例如:我想获取PNNumber 11111的最新状态。我想获取的输出是“ FOR REVIEW”。

对于PNNumber 22222,所需的输出将是“ FOR REVIEW,CANCELLED”

如何为此编写EF查询?谢谢。

c# asp.net-mvc entity-framework linq linq-to-entities
2个回答
0
投票

重新创建的数据库:

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();
}

因为我只使用了内存中的Db,所以我不知道EF将如何生成查询,但是查询的计划是:

  • 仅获取给定PNNumber的日志列表,
  • 从该过滤的列表中获取给定InsuranceCodePNNumber列表以及该PNNumberInsuranceCode的任何日志的最新日期
  • 加入结果(InsuranceCodeUpdatedOnMax(UpdatedOn)的列表
  • 从该联接中仅选择UpdatedOn == Max(UpdatedOn)的行(给定InsuranceCode的所有PNNumber的最新实体)
  • 选择Status es
  • 加入他们。

0
投票

我不知道它是否将直接转换为SQL,或者您需要首先获取整个列表,但是您应该可以使用[GroupBy][1]方法来实现。

假设您的Booking模型有一个名为ProcessStatusLogProcessStatusLogs对象的列表,它应该看起来像这样:

var result = bookings.GroupBy(
  x => x.Id,
  (_, g) => g.SelectMany(x => x.ProcessStatusLogs)
             .OrderByDescending(x => x.UpdatedOn)
             .FirstOrDefault()
);
© www.soinside.com 2019 - 2024. All rights reserved.