如何在 .net core 3.1 中订购具有空值的 IQueryable
How to order a IQueryable with null value in .net core 3.1
在我商店的主页上有一个 IQueryable 列表,它会通过不同的过滤器进行更改。
现在,例如,如果折扣价为 null,则 orderBy 时的输出将等于错误。我放了部分代码...
IQueryable<Group> result = _context.Groups
.Include(c => c.Product)
.Include(c => c.ProductGroup);
在下面的代码中,使用另一个服务接收输出
switch (getType)
{
case "all":
break;
case "discountPrice":
result = IsDiscountedProductsByGroups(result);
break;
}
尝试 OrderBy 时出现以下错误。这一步之后,会应用其他过滤器,然后填充一个ViewModel,return值为Tuple。
if (getType == "discountPrice")
{
switch (orderByType)
{
case "date":
{
result = result.OrderByDescending
(p => p.Product.CreateDate)
.ThenBy(p => p.Product.TireDiameter.Code);
break;
}
case "lowPrice":
{
result = result.OrderBy(p => p.Product.PurchasePrice)
.ThenBy(p => p.Product.TireDiameter.Code);
break;
}
case "highPrice":
{
result = result.OrderByDescending(p => p.Product.PurchasePrice)
.ThenBy(p => p.Product.TireDiameter.Code);
break;
}
}
}
已编辑问题:
添加的部分:
评论的小伙伴们好像觉得商品可能不是价格。但我不得不说不。
价格打折但可能开始或结束。
出于这个原因,当这个列表发送到以下服务时,它给出了一个空答案,并且在 orderBy:
时会遇到错误
public IQueryable<Group> IsDiscountedProductsByGroups(IQueryable<Group> groups)
{
foreach (var item in groups)
{
if (item.Product.PurchasePrice != null)
{
if (item.Product.StartDiscountTime != null && item.Product.StartDiscountTime < DateTime.Now)
{
if (item.Product.EndDiscountTime != null && item.Product.EndDiscountTime > DateTime.Now)
{
listDiscountedProductsByGroup.Append(item);
}
}
}
}
return listDiscountedProductsByGroup;
}
试试这个:
result = result.OrderByDescending(p => p.Product.PurchasePrice.HasValue)
如果您想包含可能有价格也可能没有价格的产品,并将没有价格的产品视为 0(或任何其他值),请尝试如下操作:
result.OrderBy(p => p.Product.PurchasePrice.HasValue ? p.Product.PurchasePrice.Value : 0);
如果你想让它们放在列表的末尾,你可以使用一个非常大的幻数来代替上面的“0”,或者更好:
result.OrderBy(p => p.Product.PurchasePrice.HasValue ? 0 : 1)
.ThenBy(p => p.Product.PurchasePrice.HasValue ? p.Product.PurchasePrice.Value : 0);
这会把有价格的按价格排序,然后把没有价格的移到最后。
如果您想排除没有购买价格的产品,则需要使用 Where
子句将其过滤掉。
result.Where(p => p.Product.PurchasePrice.HasValue)
.OrderBy(p => p.Product.PurchasePrice.Value);
更新:好的,根据您更新后的实施,有几个问题:
#1。从您的示例中,不清楚 listDiscountedProductsByGroup 的声明位置。
#2。您的日期比较逻辑中似乎存在一个错误,即折扣开始和结束预计都将小于现在。通常这将是 Start <= now && End >= now.
#3。您的“IsDiscountedProductsByGroups”方法采用 EF IQueryable,并且可能 return 一组实体化实体,这些实体可能是 IQueryable,但将不再派生到 SQL,而是在内存中进行处理。如果你所做的只是应用排序,这不是什么大问题,但如果你想应用任何其他过滤或使用 Skip
/Take
对结果进行分页,这会破坏 EF 优化以发送到 SQL.
相反,这可能是您要查找的内容:
IQueryable<Group> result = _context.Groups
.Include(c => c.Product)
.Include(c => c.ProductGroup);
if (getType == "discountPrice")
{
var now = DateTime.Now;
result = result.Where(x => x.Product.PurchasePrice != null
&& x.Product.StartDiscountTime.HasValue
&& x.Product.StartDiscountTime < now
&& x.Product.EndDiscountTime.HasValue
&& x.Product.EndDiscountTime > now);
}
... 然后从这里追加适当的 OrderBy。这将确保 IQueryable
仍然是 EF 可查询的。
这假设您只想要具有今天折扣的产品的商品。这看起来有点奇怪,因为我希望产品会有更多的价格历史,或者折扣的想法会被单独跟踪。
在我商店的主页上有一个 IQueryable 列表,它会通过不同的过滤器进行更改。 现在,例如,如果折扣价为 null,则 orderBy 时的输出将等于错误。我放了部分代码...
IQueryable<Group> result = _context.Groups
.Include(c => c.Product)
.Include(c => c.ProductGroup);
在下面的代码中,使用另一个服务接收输出
switch (getType)
{
case "all":
break;
case "discountPrice":
result = IsDiscountedProductsByGroups(result);
break;
}
尝试 OrderBy 时出现以下错误。这一步之后,会应用其他过滤器,然后填充一个ViewModel,return值为Tuple。
if (getType == "discountPrice")
{
switch (orderByType)
{
case "date":
{
result = result.OrderByDescending
(p => p.Product.CreateDate)
.ThenBy(p => p.Product.TireDiameter.Code);
break;
}
case "lowPrice":
{
result = result.OrderBy(p => p.Product.PurchasePrice)
.ThenBy(p => p.Product.TireDiameter.Code);
break;
}
case "highPrice":
{
result = result.OrderByDescending(p => p.Product.PurchasePrice)
.ThenBy(p => p.Product.TireDiameter.Code);
break;
}
}
}
已编辑问题:
添加的部分:
评论的小伙伴们好像觉得商品可能不是价格。但我不得不说不。 价格打折但可能开始或结束。 出于这个原因,当这个列表发送到以下服务时,它给出了一个空答案,并且在 orderBy:
时会遇到错误public IQueryable<Group> IsDiscountedProductsByGroups(IQueryable<Group> groups)
{
foreach (var item in groups)
{
if (item.Product.PurchasePrice != null)
{
if (item.Product.StartDiscountTime != null && item.Product.StartDiscountTime < DateTime.Now)
{
if (item.Product.EndDiscountTime != null && item.Product.EndDiscountTime > DateTime.Now)
{
listDiscountedProductsByGroup.Append(item);
}
}
}
}
return listDiscountedProductsByGroup;
}
试试这个:
result = result.OrderByDescending(p => p.Product.PurchasePrice.HasValue)
如果您想包含可能有价格也可能没有价格的产品,并将没有价格的产品视为 0(或任何其他值),请尝试如下操作:
result.OrderBy(p => p.Product.PurchasePrice.HasValue ? p.Product.PurchasePrice.Value : 0);
如果你想让它们放在列表的末尾,你可以使用一个非常大的幻数来代替上面的“0”,或者更好:
result.OrderBy(p => p.Product.PurchasePrice.HasValue ? 0 : 1)
.ThenBy(p => p.Product.PurchasePrice.HasValue ? p.Product.PurchasePrice.Value : 0);
这会把有价格的按价格排序,然后把没有价格的移到最后。
如果您想排除没有购买价格的产品,则需要使用 Where
子句将其过滤掉。
result.Where(p => p.Product.PurchasePrice.HasValue)
.OrderBy(p => p.Product.PurchasePrice.Value);
更新:好的,根据您更新后的实施,有几个问题:
#1。从您的示例中,不清楚 listDiscountedProductsByGroup 的声明位置。
#2。您的日期比较逻辑中似乎存在一个错误,即折扣开始和结束预计都将小于现在。通常这将是 Start <= now && End >= now.
#3。您的“IsDiscountedProductsByGroups”方法采用 EF IQueryable,并且可能 return 一组实体化实体,这些实体可能是 IQueryable,但将不再派生到 SQL,而是在内存中进行处理。如果你所做的只是应用排序,这不是什么大问题,但如果你想应用任何其他过滤或使用 Skip
/Take
对结果进行分页,这会破坏 EF 优化以发送到 SQL.
相反,这可能是您要查找的内容:
IQueryable<Group> result = _context.Groups
.Include(c => c.Product)
.Include(c => c.ProductGroup);
if (getType == "discountPrice")
{
var now = DateTime.Now;
result = result.Where(x => x.Product.PurchasePrice != null
&& x.Product.StartDiscountTime.HasValue
&& x.Product.StartDiscountTime < now
&& x.Product.EndDiscountTime.HasValue
&& x.Product.EndDiscountTime > now);
}
... 然后从这里追加适当的 OrderBy。这将确保 IQueryable
仍然是 EF 可查询的。
这假设您只想要具有今天折扣的产品的商品。这看起来有点奇怪,因为我希望产品会有更多的价格历史,或者折扣的想法会被单独跟踪。