[英]Convert duplicated Linq OrderBy in EF Core WHERE clause to be more readable
I am trying to query a list of objects based on the ordering of child items.我正在尝试根据子项的顺序查询对象列表。 I have this query that works, but as you can see the where clause is excessively long because of the duplicated orderby.
我有这个有效的查询,但正如您所见,由于重复的 orderby,where 子句过长。
List<Driver> driversToReturn = new List<Driver>();
var drivers = await _rwContext.Drivers
.Include(d => d.RegionIds)
.Include(d => d.Carrier).ThenInclude(c => c.DriverHolds)
.Include(m => m.Manifests).ThenInclude(m => m.ManifestStops)
.ThenInclude(ms => ms.OffloadJourneys).ThenInclude(o => o.EndLocation).ThenInclude(o => o.LocationAliases.Where(la => la.IsPrimary))
.Include(m => m.Manifests).ThenInclude(m => m.ManifestStops)
.ThenInclude(ms => ms.OnloadJourneys).ThenInclude(o => o.StartLocation).ThenInclude(o => o.LocationAliases.Where(la => la.IsPrimary))
.Where(m =>
((startDate == null || endDate == null || m.Manifests == null || m.Manifests.Count ==0
|| (m.Manifests.FirstOrDefault(m => m.ManifestStops != null && m.ManifestStops
.OrderBy(ms => ms.StopTimestamp != null &&
ms.StopTimeSet ?
ms.StopTimestamp :
(!ms.StopTimeSet && ms.StopTimestamp != null ?
(ms.IsOffloadStop ?
ms.StopTimestamp.Value.AddHours((23 - ms.StopTimestamp.Value.Hour)).AddMinutes((59 - ms.StopTimestamp.Value.Minute)) :
ms.StopTimestamp.Value.AddHours(-1 * (ms.StopTimestamp.Value.Hour)).AddMinutes(-1 * (ms.StopTimestamp.Value.Minute))) :
(ms.IsOffloadStop ? DateTime.Now.AddYears(10) : DateTime.Now.AddYears(-10)))).ThenBy(ms => ms.IsOffloadStop)
.LastOrDefault() != null
&& startDate <= m.ManifestStops
.OrderBy(ms => ms.StopTimestamp != null &&
ms.StopTimeSet ?
ms.StopTimestamp :
(!ms.StopTimeSet && ms.StopTimestamp != null ?
(ms.IsOffloadStop ?
ms.StopTimestamp.Value.AddHours((23 - ms.StopTimestamp.Value.Hour)).AddMinutes((59 - ms.StopTimestamp.Value.Minute)) :
ms.StopTimestamp.Value.AddHours(-1 * (ms.StopTimestamp.Value.Hour)).AddMinutes(-1 * (ms.StopTimestamp.Value.Minute))) :
(ms.IsOffloadStop ? DateTime.Now.AddYears(10) : DateTime.Now.AddYears(-10)))).ThenBy(ms => ms.IsOffloadStop)
.LastOrDefault().StopTimestamp
&& endDate.Value.Date.AddDays(1) > m.ManifestStops
.OrderBy(ms => ms.StopTimestamp != null &&
ms.StopTimeSet ?
ms.StopTimestamp :
(!ms.StopTimeSet && ms.StopTimestamp != null ?
(ms.IsOffloadStop ?
ms.StopTimestamp.Value.AddHours((23 - ms.StopTimestamp.Value.Hour)).AddMinutes((59 - ms.StopTimestamp.Value.Minute)) :
ms.StopTimestamp.Value.AddHours(-1 * (ms.StopTimestamp.Value.Hour)).AddMinutes(-1 * (ms.StopTimestamp.Value.Minute))) :
(ms.IsOffloadStop ? DateTime.Now.AddYears(10) : DateTime.Now.AddYears(-10)))).ThenBy(ms => ms.IsOffloadStop)
.LastOrDefault().StopTimestamp) == null) &&
(m.Manifests.FirstOrDefault(m => m.ManifestStops != null && m.ManifestStops
.OrderBy(ms => ms.StopTimestamp != null &&
ms.StopTimeSet ?
ms.StopTimestamp :
(!ms.StopTimeSet && ms.StopTimestamp != null ?
(ms.IsOffloadStop ?
ms.StopTimestamp.Value.AddHours((23 - ms.StopTimestamp.Value.Hour)).AddMinutes((59 - ms.StopTimestamp.Value.Minute)) :
ms.StopTimestamp.Value.AddHours(-1 * (ms.StopTimestamp.Value.Hour)).AddMinutes(-1 * (ms.StopTimestamp.Value.Minute))) :
(ms.IsOffloadStop ? DateTime.Now.AddYears(10) : DateTime.Now.AddYears(-10)))).ThenBy(ms => ms.IsOffloadStop)
.FirstOrDefault() != null
&& endDate.Value.Date.AddDays(1) > m.ManifestStops
.OrderBy(ms => ms.StopTimestamp != null &&
ms.StopTimeSet ?
ms.StopTimestamp :
(!ms.StopTimeSet && ms.StopTimestamp != null ?
(ms.IsOffloadStop ?
ms.StopTimestamp.Value.AddHours((23 - ms.StopTimestamp.Value.Hour)).AddMinutes((59 - ms.StopTimestamp.Value.Minute)) :
ms.StopTimestamp.Value.AddHours(-1 * (ms.StopTimestamp.Value.Hour)).AddMinutes(-1 * (ms.StopTimestamp.Value.Minute))) :
(ms.IsOffloadStop ? DateTime.Now.AddYears(10) : DateTime.Now.AddYears(-10)))).ThenBy(ms => ms.IsOffloadStop)
.FirstOrDefault().StopTimestamp
&& startDate <= m.ManifestStops
.OrderBy(ms => ms.StopTimestamp != null &&
ms.StopTimeSet ?
ms.StopTimestamp :
(!ms.StopTimeSet && ms.StopTimestamp != null ?
(ms.IsOffloadStop ?
ms.StopTimestamp.Value.AddHours((23 - ms.StopTimestamp.Value.Hour)).AddMinutes((59 - ms.StopTimestamp.Value.Minute)) :
ms.StopTimestamp.Value.AddHours(-1 * (ms.StopTimestamp.Value.Hour)).AddMinutes(-1 * (ms.StopTimestamp.Value.Minute))) :
(ms.IsOffloadStop ? DateTime.Now.AddYears(10) : DateTime.Now.AddYears(-10)))).ThenBy(ms => ms.IsOffloadStop)
.FirstOrDefault().StopTimestamp) == null)
)) &&
(m.Carrier == null || m.CarrierId ==0 || m.Carrier.DriverHolds == null || m.Carrier.DriverHolds.Count == 0 ||
(m.Carrier.DriverHolds.FirstOrDefault(dr => dr.DriverId == m.DriverId &&
(startDate == null || endDate == null || (dr.StartDate > startDate.Value && dr.StartDate < endDate.Value.Date.AddDays(1))) &&
(endDate == null || endDate == null || (dr.EndDate > startDate.Value && dr.EndDate < endDate.Value.Date.AddDays(1)))) == null)
) && (RegionId == null || m.RegionIds.FirstOrDefault(r => r.RegionId == RegionId) != null))
.Select(r => new
{
DriverId = r.DriverId,
DriverTag = r.DriverTag,
RegionIds = r.RegionIds.Select(r=>new RegionIdItem() {
RegionId = r.RegionId,
DriverId = r.DriverId
}),
Carrier = new {
CarrierId = r.Carrier.CarrierId,
CarrierTag = r.Carrier.CarrierTag,
DriverHolds = r.Carrier.DriverHolds.Where(dh=>dh.DriverId == r.DriverId).Select(dh => new DriverHold() {
StartDate = dh.StartDate,
EndDate = dh.EndDate,
DriverId = dh.DriverId,
})
},
Manifests = r.Manifests.Select(m => new {
ManifestId = m.ManifestId,
ManifestStops = m.ManifestStops
.Select(ms => new {
//manifest stop
StopTimeSet = ms.StopTimeSet,
StopTimestamp = ms.StopTimestamp,
OffloadJourneys = ms.OffloadJourneys.Select(oj => new {
EndLocation = new {
LocationAliases = oj.EndLocation.LocationAliases.Where(la => la.IsPrimary).Select(la => new LocationAlias()
{
Alias = la.Alias,
IsPrimary = la.IsPrimary
})
}
}),
//manifest stop
OnloadJourneys = ms.OnloadJourneys.Select(oj => new
{
StartLocation = new
{
LocationAliases = oj.StartLocation.LocationAliases.Where(la => la.IsPrimary).Select(la => new LocationAlias()
{
Alias = la.Alias,
IsPrimary = la.IsPrimary
})
}
})
})
})
})
.ToListAsync(ct);
I tried to apply the OrderBy to the 'ThenInclude' where I am selecting 'ManifestStops' but that didn't take effect before the WHERE clause and the ordering was not preserved in the Where query.我尝试将 OrderBy 应用于选择“ManifestStops”的“ThenInclude”,但这在 WHERE 子句之前没有生效,并且排序未保留在 Where 查询中。
I also tried to apply the ordering in the select clause but had the same problem as doing it in the 'ThenInclude'.我还尝试在 select 子句中应用排序,但遇到与在“ThenInclude”中执行此操作相同的问题。
Another approach I attempted was to add an extension method to do this but I got an EF 'Query could not be translated' error.我尝试的另一种方法是添加一个扩展方法来执行此操作,但我收到了一个 EF 'Query could not be translate' 错误。
public static IEnumerable<ManifestStop> OrderManifestStops(this IEnumerable<ManifestStop> source)
{
return source.OrderBy(ms => ms.StopTimestamp != null &&
ms.StopTimeSet ?
ms.StopTimestamp :
(!ms.StopTimeSet && ms.StopTimestamp != null ?
(ms.IsOffloadStop ?
ms.StopTimestamp.Value.AddHours((23 - ms.StopTimestamp.Value.Hour)).AddMinutes((59 - ms.StopTimestamp.Value.Minute)) :
ms.StopTimestamp.Value.AddHours(-1 * (ms.StopTimestamp.Value.Hour)).AddMinutes(-1 * (ms.StopTimestamp.Value.Minute))) :
(ms.IsOffloadStop ? DateTime.Now.AddYears(10) : DateTime.Now.AddYears(-10)))).ThenBy(ms => ms.IsOffloadStop);
}
I guess Driver
has an implementation close to that我猜
Driver
有一个接近那个的实现
public class Driver
{
public DateTime? StopTimestamp { get; set; }
public bool StopTimeSet { get; set; }
public bool IsOffloadStop { get; set; }
}
You can create static field OrderBy
您可以创建 static 字段
OrderBy
public static Func<Driver, DateTime?> OrderBy
= ms => (ms.StopTimestamp != null && ms.StopTimeSet)
? ms.StopTimestamp
: (!ms.StopTimeSet && ms.StopTimestamp != null)
? (ms.IsOffloadStop
? ms.StopTimestamp.Value.AddHours((23 - ms.StopTimestamp.Value.Hour)).AddMinutes((59 - ms.StopTimestamp.Value.Minute))
: ms.StopTimestamp.Value.AddHours(-1 * (ms.StopTimestamp.Value.Hour)).AddMinutes(-1 * (ms.StopTimestamp.Value.Minute)))
: ms.IsOffloadStop
? DateTime.Now.AddYears(10)
: DateTime.Now.AddYears(-10);
And use it, for example like this:并使用它,例如这样:
var drivers = new List<Driver>();
drivers.OrderBy(OrderBy);
But I doubt that it can be translated by EF
但是我怀疑它可以被
EF
翻译
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.