使用EntityFramework Core选择每个客户的最低付款记录

时间:2018-09-24 19:01:02

标签: c# entity-framework-core

我有一个可将客户与库存车辆匹配的应用程序。有3个主要表格:“客户”,“匹配”和“库存”。匹配记录包含特定客户和库存记录的估计每月付款。一个客户可以与库存中的多个车辆匹配。

匹配记录包含一个CustomerId和一个InventoryId,以及一个MonthlyPayment字段和其他一些杂项字段。

客户与匹配之间存在一对多的关系。 库存和匹配之间存在一对多的关系。

对于每个客户,我想选择“客户”记录,每月付款最低的匹配记录以及该匹配的“库存”记录。

做到这一点的最佳方法是什么?可以通过单个查询完成吗?

我尝试了这段代码,但是实体框架无法评估它,而是在本地执行它,这会降低性能。

var bestMatches = _matchRepository.GetAll(customerMatchSummaryRequest)
                              .Where(match =>
                                    (_matchRepository.GetAll(customerMatchSummaryRequest)
                                    .GroupBy(m => new { m.Bpid, m.BuyerId, m.CurrentVehicleId })
                                    .Select(g => new
                                    {
                                        g.Key.Bpid,
                                        g.Key.BuyerId,
                                        g.Key.CurrentVehicleId,
                                        LowestMonthlyPayment = g.Min(m => m.MonthlyPayment)
                                    })
                                    .Where(m => m.Bpid == match.Bpid
                                        && m.BuyerId == match.BuyerId
                                        && m.CurrentVehicleId == match.CurrentVehicleId
                                        && m.LowestMonthlyPayment == match.MonthlyPayment)
                                  ).Any())
                              .Include(m => m.Buyer)
                              .Include(m => m.Inventory);

单步调试器时,我收到以下输出:

Microsoft.EntityFrameworkCore.Query:Warning: The LINQ expression 'GroupBy(new <>f__AnonymousType2`3(Bpid = [<generated>_2].Bpid, BuyerId = [<generated>_2].BuyerId, CurrentVehicleId = [<generated>_2].CurrentVehicleId), [<generated>_2])' could not be translated and will be evaluated locally.
Microsoft.EntityFrameworkCore.Query:Warning: The LINQ expression 'GroupBy(new <>f__AnonymousType2`3(Bpid = [<generated>_2].Bpid, BuyerId = [<generated>_2].BuyerId, CurrentVehicleId = [<generated>_2].CurrentVehicleId), [<generated>_2])' could not be translated and will be evaluated locally.

1 个答案:

答案 0 :(得分:2)

假设您的模型是这样的

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Match> Matches { get; set; }
}

public class Inventory
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Match> Matches { get; set; }
}

public class Match
{
    public int CustomerId { get; set; }
    public Customer Custmer { get; set; }
    public int InventoryId { get; set; }
    public Inventory Inventory { get; set; }
    public decimal MonthlyPayment { get; set; }
}

有问题的查询可能是这样的:

var query =
    from customer in db.Set<Customer>()
    from match in customer.Matches
    where !customer.Matches.Any(m => m.MonthlyPayment > match.MonthlyPayment)
    select new
    {
        Customer = customer,
        Match = match,
        Inventory = match.Inventory
    };

请注意,如果它包含多个付款最低的库存记录,则它可能为客户返回多个匹配项。如果数据允许,并且您希望每个客户获得0或1个结果,请更改

m.MonthlyPayment > match.MonthlyPayment

条件

m.MonthlyPayment > match.MonthlyPayment ||
(m.MonthlyPayment == match.MonthlyPayment && m.InventoryId < match.InventoryId)

P.S。上面的LINQ查询是当前转换为单个SQL查询的唯一方法。不幸的是,更自然的方式

    from customer in db.Set<Customer>()
    let match = customer.Matches.OrderBy(m => m.MonthlyPayment).FirstOrDefault()
    ...

    from customer in db.Set<Customer>()
    from match in customer.Matches.OrderBy(m => m.MonthlyPayment).Take(1)
    ...

指向client evaluation