我有一个用于生产线的数据库。它有一个 Orders 表、Ordertracker 表、Item 表和 Itemtracker 表。
订单和商品都与状态存在多对多关系。跟踪器表以这样的方式解析这些关系:一个项目可以在跟踪器中具有多个条目 - 每个条目都有一个特定的状态。
我尝试上传表格图片以使事情更清楚,但可惜,我还没有足够的积分:C
我需要查找 Itemtracker 表中最后状态满足条件(“3”或“0”)的项目。
然后我需要获得这些项目中的第一个。
我用来完成此操作的步骤如下:
- 获取所有具有特定状态的订单。
- 获取该订单中的所有商品。
- 获取最后状态 = 0 或 3 的所有项目。
- 获取第一项。
我的代码如下:
public ITEM GetFirstItemFailedOrNotInProductionFromCurrentOrder()
{
var firstOrder = GetFirstOrderInProductionAndNotCompleted();
var items = ERPContext.ITEM.Where(i => i.OrderID == firstOrder.OrderID) as IQueryable<ITEM>;
if (CheckStatusOfItems(items) != null)
{
var nextItem = CheckStatusOfItems(items);
return nextItem ;
}
else
{
return null;
}
}
private ITEM CheckStatusOfItems(IQueryable<ITEM> items)
{
List<ITEM> listOfItemsToProduce = new List<ITEM>();
foreach (ITEM item in items.ToList())
{
var lastStatusOfItem = ERPContext.ITEMTRACKER.Where(it => it.ItemID == item.ItemID)
.OrderByDescending(it => it.ItemTrackerID).FirstOrDefault();
if (lastStatusOfItem.ItemStatus == (int)ItemStatus.Failed || lastStatusOfItem.ItemStatus == (int)ItemStatus.Confirmed)
{
listOfItemsToProduce.Add(item);
}
}
return listOfItemsToProduce.FirstOrDefault();
}
现在,这一切都工作正常并返回我需要的内容,但我知道这可能不是最好的方法。因为现在我的 IQueryable 项目集合永远不会包含超过 6 个项目 - 但如果它可能变得更大,那么在 IQueryable 上调用 ToList() 并迭代内存中的结果可能不是一个好主意。
是否有更好的方法来迭代 IQueryable 项目以获取具有特定状态的项目作为其最新状态,而无需调用 ToList() 并遍历结果?
如有任何建议,我们将不胜感激。
最佳答案
使用 LINQ 查询语法,您可以以声明方式构建单个查询,这与编写命令式迭代的方式几乎相同。 foreach
转换为 from
,var
转换为 let
,if
转换为 where
:
private ITEM CheckStatusOfItems(IQueryable<ITEM> items)
{
var query =
from item in items
let lastStatusOfItem = ERPContext.ITEMTRACKER
.Where(it => it.ItemID == item.ItemID)
.OrderByDescending(it => it.ItemTrackerID)
.FirstOrDefault()
where (lastStatusOfItem.ItemStatus == (int)ItemStatus.Failed || lastStatusOfItem.ItemStatus == (int)ItemStatus.Confirmed)
select item;
return query.FirstOrDefault();
}
或者使用 from
代替 let
并使用 Take(1)
代替 FirstOrDefault()
:
private ITEM CheckStatusOfItems(IQueryable<ITEM> items)
{
var query =
from item in items
from lastStatusOfItem in ERPContext.ITEMTRACKER
.Where(it => it.ItemID == item.ItemID)
.OrderByDescending(it => it.ItemTrackerID)
.Take(1)
where (lastStatusOfItem.ItemStatus == (int)ItemStatus.Failed || lastStatusOfItem.ItemStatus == (int)ItemStatus.Confirmed)
select item;
return query.FirstOrDefault();
}
关于c# - 迭代 IQueryable 而不调用 ToList(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47113495/