C# 使用Linq检查孙子列表时删除子列表项

C# 使用Linq检查孙子列表时删除子列表项,c#,linq,C#,Linq,以下代码显示如何将数据分配到IEnumerable 有一个列表(IEnumerable)有另一个列表(list),该子列表(list)上有一个列表。但是AllocationDetailList只有一个列表项 public IEnumerable<UnCompletedJobDetailsBO> GetControlDetails(DateTime startDate) { var controlDetails = (from booking in db.Book

以下代码显示如何将数据分配到
IEnumerable

有一个列表(
IEnumerable
)有另一个列表(
list
),该子列表(
list
)上有一个列表。但是
AllocationDetailList
只有一个列表项

public IEnumerable<UnCompletedJobDetailsBO> GetControlDetails(DateTime startDate)
{
    var controlDetails =
       (from booking in db.BookingDetail
        where booking.BookingDateTime >= startDate
        orderby booking.DocketNo
        select new UnCompletedJobDetailsBO()
        {
            CustomerName = booking.Customer.Name,
            CompanyName = booking.CompanyDetail.Name,
            JobList =
               (from job in db.BookingJob.Where(x => x.BookingID == booking.BookingID) //get job list
                select new JobDetailsBO()
                {
                    JobID = job.JobID,
                    JobType = job.JobType,
                    ItemName = job.ItemName,
                    AllocationDetailList =
                       (from jobAllocationDetail in db.JobAllocation
                        join returnUnCollected in db.JobReturnUnCollected
                            on jobAllocationDetail.JobAllocationDetailID
                            equals returnUnCollected.JobAllocationDetailID
                            into returnJob

                        from returnUnCollected in returnJob.DefaultIfEmpty()
                        where (jobAllocationDetail.Booking.BookingID == booking.BookingID)
                        select new AllocationBO()
                        {
                            JobUnCollectedID = returnJob.JobUnCollectedID,
                            JobType = jobAllocationDetail.JobType,
                            CurrentStatus = jobAllocationDetail.CurrentStatus,
                        }).DefaultIfEmpty().ToList(),
                }).DefaultIfEmpty().ToList(),
        }).ToList();

    return controlDetails;
}
如果没有,我不确定是否可以解决任何性能问题。要完全理解问题本身是很困难的,但是如果不能实际测试代码、复制和观察特定的性能问题,就很难确定您的问题具体在哪里,更不用说如何解决它了

也就是说,从您发布的代码中,可以清楚地看出为什么没有从列表中删除项目。基本问题是,虽然
SelectMany()
方法确实允许您将所有不同
JobList
对象中的所有元素作为单个枚举枚举,但这些元素将作为新枚举枚举

当您调用
ToList()
时,您正在从该新枚举创建一个全新的列表,而当您调用
RemoveAll()
时,您只是在从该新列表中删除元素,而不是它们最初来自的列表

您说您可以让它与
for
循环一起工作。我想你的意思是这样的:

public List<UnCompletedJobDetailsBO> RemovePODFromSelectedList(
    List<UnCompletedJobDetailsBO> unCompletedJobDetailsBO)
{
    foreach (var item in unCompletedJobDetailsBO)
    {
        item.JobList.RemoveAll(x => ((x.AllocationDetailList[0] != null) ?
            x.AllocationDetailList[0].JobType == "D" &&
                x.AllocationDetailList[0].JobUnCollectedID == null &&
                x.AllocationDetailList[0].CurrentStatus == 5 :
            x.AllocationDetailList.Count > 1));
    }

    return unCompletedJobDetailsBO;
}
public List从selectedlist中删除pod(
列出未完成的作业详细信息(SBO)
{
foreach(未完成的JobDetailsBO中的var项)
{
item.JobList.RemoveAll(x=>((x.AllocationDetailList[0]!=null))是否为空?
x、 AllocationDetailList[0]。作业类型==“D”&&
x、 AllocationDetailList[0]。JobUnCollectedID==null&&
x、 AllocationDetailList[0]。CurrentStatus==5:
x、 AllocationDetailList.Count>1);
}
返回未完成的JobDetailsBO;
}
注意:不需要返回
未完成的ObjDetailsBO
。整个对象是不变的,更不用说变量了。代码唯一要修改的是传入对象成员中的每个
作业列表
对象。也就是说,上述方法实际上可以有一个返回类型
void
,并且可以完全删除
return
语句

您可以通过以不同的方式删除元素来加快代码的速度。
List.RemoveAll()
方法实际上相当有效,成本为O(n)。但它仍然需要在删除第一个元素后复制列表中的所有数据(以便所有元素在列表中下移)。如果您必须对列表进行排序,这可能是您所能做的最好的事情,但是如果没有,您可以以不同的方式处理删除,或者使用不同的数据结构,在无序的情况下删除一个或多个元素的成本更低

但是,没有更多的细节,也没有一个很好的例子来解决这个特定的问题,在这里似乎是不现实的

x.AllocationDetailList[0] != null 
如果AllocationDetailList中没有项,将引发异常。相反,你需要检查一下

x.AllocationDetailList!=null && x.AllocationDetailList.Count>0.
另外,在代码中选择many后的.ToList()将创建一个新列表,项目将从该新列表中删除,而不是从未完成的ObjDetailsBO中删除。您需要修改删除功能,如下所示

   unCompletedJobDetailsBO.ForEach(y => y.JobList.RemoveAll(x => ((x.AllocationDetailList != null && x.AllocationDetailList.Count>0) 
                                                                         ?
                                                                         x.AllocationDetailList[0].JobType == "D"
                                                                           && x.AllocationDetailList[0].JobUnCollectedID == null
                                                                           && x.AllocationDetailList[0].CurrentStatus == "5" 
                                                                         :
                                                                        x.AllocationDetailList.Count > 1
                                                                         )
                                                                   ));

很抱歉,没有提供完整的代码。此代码位于同一DA文件中。我想将筛选后的列表放入我的控制器。我同意你的回答。如果没有forloop/foreach,我就做不到?考虑到目前为止提供的信息,不……如果不访问主列表中的每个
UnCompletedJobDetailsBO
对象,我看不到一种方法可以做到这一点。请注意,即使您的非工作示例也确实做到了这一点……它只是以一种不太明显的方式做到了这一点。它在过滤之前加载所有列表。这与使用foreach相同。在延迟/延迟级别,这是任何可能的方法。删除所有需要列表。谢谢。我不知道你说的“懒惰/延迟级别”是什么意思。但是,您可以通过删除最后一个
ToList()
来推迟原始查询,并且您可以在
作业列表
属性的初始化中添加
where
,以考虑您想要执行的一些筛选,这样元素就不会首先出现在列表中。我不清楚你问的是什么。我的第一个错误是在查询中使用ToList()。如果我没有使用ToList,我的输出应该是IEnumerable。但无法对IEnumerable应用RemoveAll()。有没有办法从IEnumerable中删除项而不应用查询中的where
   unCompletedJobDetailsBO.ForEach(y => y.JobList.RemoveAll(x => ((x.AllocationDetailList != null && x.AllocationDetailList.Count>0) 
                                                                         ?
                                                                         x.AllocationDetailList[0].JobType == "D"
                                                                           && x.AllocationDetailList[0].JobUnCollectedID == null
                                                                           && x.AllocationDetailList[0].CurrentStatus == "5" 
                                                                         :
                                                                        x.AllocationDetailList.Count > 1
                                                                         )
                                                                   ));