c# - 迭代 IQueryable 而不调用 ToList()

标签 c# database linq foreach iqueryable

我有一个用于生产线的数据库。它有一个 Orders 表、Ordertracker 表、Item 表和 Itemtracker 表。

订单和商品都与状态存在多对多关系。跟踪器表以这样的方式解析这些关系:一个项目可以在跟踪器中具有多个条目 - 每个条目都有一个特定的状态。

我尝试上传表格图片以使事情更清楚,但可惜,我还没有足够的积分:C

我需要查找 Itemtracker 表中最后状态满足条件(“3”或“0”)的项目。

然后我需要获得这些项目中的第一个。

我用来完成此操作的步骤如下:

  1. 获取所有具有特定状态的订单。
  2. 获取该订单中的所有商品。
  3. 获取最后状态 = 0 或 3 的所有项目。
  4. 获取第一项。

我的代码如下:

    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 转换为 fromvar 转换为 letif 转换为 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/

相关文章:

mysql - 在主键上创建和索引有什么好处吗?

c# - 从连接字符串中删除了数据库

database - 同一张表中的多对多关系?

c# - 如何使用 linq 向关系表中的实体添加数据?

python - 从预先存在的列表 VB.Net 生成对象属性列表

c# - 如何以编程方式将 RibbonTab 添加到 WPF 功能区(2010 年 10 月版本)?

C#:处理 WebClient "protocol violation"

c# - 如何使任务栏缩略图上的区域在 Windows 7 中显示为透明?

c# - 你能在正则表达式中向后阅读吗?

c# - Queryable.Single 上的 IndexOutOfRangeException