我有一个可将客户与库存车辆匹配的应用程序。有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.
答案 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)
...