简体   繁体   English

遍历IQueryable而不调用ToList()

[英]Iterate over an IQueryable without calling ToList()

I have a DB used for a production line. 我有一个用于生产线的数据库。 It has an Orders table, and Ordertracker table, an Item table, and an Itemtracker table. 它具有一个Orders表,一个Ordertracker表,一个Item表和一个Itemtracker表。

Both Orders and Items have many-to-many relationships with status. 订单和项目都与状态具有多对多关系。 The tracker tables resolves these relationships in such a way that an item can have multiple entries in the tracker - each with a particular status. 跟踪器表通过以下方式解析这些关系:项目可以在跟踪器中具有多个条目-每个条目都具有特定的状态。

I tried to upload a picture of the tables to make things clearer but alas, I don't have enough points yet :C 我试图上传一张桌子的图片以使情况更清楚,但是,我还没有足够的要点:C

I need to find items whose last status in the Itemtracker table meets a condition, either '3' or '0'. 我需要找到在Itemtracker表中最后一个状态满足“ 3”或“ 0”条件的项目。

I then need to get the first one of these items. 然后,我需要获得这些物品中的第一个。

The steps I am using to accomplish this are as follows: 我用来完成此操作的步骤如下:

  1. Get all the Orders which have a certain status. 获取具有一定状态的所有订单。
  2. Get all the Items in that Order. 获取该订单中的所有项目。
  3. Get all the Items whose last status was = 0 or 3. 获取所有状态为0或3的项目。
  4. Get the first of these items. 获取这些项目中的第一个。

My code is as follows: 我的代码如下:

    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();

    }

Now, this all works fine and returns what I need but I'm aware that this might not be the best approach. 现在,这一切都可以正常工作并返回我需要的东西,但是我知道这可能不是最好的方法。 As it is now my IQueryable collection of items will never contain more than 6 items - but if it could grow larger, then calling ToList() on the IQueryable and iterating over the results in-memory would probably not be a good idea. 到现在为止,我的IQueryable项目集合将永远不会包含超过6个项目-但是,如果它可能变得更大,则在IQueryable上调用ToList()并在内存中迭代结果可能不是一个好主意。

Is there a better way to iterate through the IQueryable items to fetch out the items that have a certain status as their latest status without calling ToList() and foreaching through the results? 有没有更好的方法可以遍历IQueryable项以获取具有特定状态的项作为最新状态,而无需调用ToList()并遍历结果呢?

Any advice would be much appreciated. 任何建议将不胜感激。

Using LINQ query syntax, you can build declaratively a single query pretty much the same way you wrote the imperative iteration. 使用LINQ查询语法,您可以声明性地构建单个查询,几乎与编写命令式迭代的方式相同。 foreach translates to from , var to let and if to where : foreach转换为fromvarlet以及ifwhere

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();
}

or alternatively using from instead of let and Take(1) instead of FirstOrDefault() : 或使用from代替letTake(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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用forEach与调用ToList()在IQueryable上进行迭代,然后再进行forEach-性能 - Iterating over IQueryable with forEach vs. calling ToList() and then doing forEach - performance 我已经读过迭代HashSet是不好的做法。 我应该首先调用.ToList()吗? - I have read that it is bad practice to iterate over a HashSet. Should I be calling .ToList() on it first? IQueryable不包含ToList() - IQueryable does not contain ToList() ToList() 方法在哪里? (可查询) - Where is the ToList() method? (IQueryable) 需要IQueryable ToArray和ToList链接 - Need for IQueryable ToArray AND ToList chained 强制IEnumerable <T> 无需调用.ToArray()或.ToList()进行评估 - Force IEnumerable<T> to evaluate without calling .ToArray() or .ToList() 当结果很可能时,IQueryable ToList()是否优于.Count()? - Is IQueryable ToList() preferred to .Count() when results are probable? C#-可查询以列出异步-EF6 - C# - IQueryable to ToList Async - EF6 冻结linq IQueryable(就像ToList()。AsQueryable()那样) - Freeze a linq IQueryable (as a ToList().AsQueryable() would do) 谓词 where 条件在 IQueryable 中不起作用但在将 IQueryable 转换为 ToList() 后起作用 - Predicate where condition is not working in IQueryable but working after converted IQueryable to ToList()
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM