C# 从常规列表中删除项目不起作用

C# 从常规列表中删除项目不起作用,c#,entity-framework,linq,C#,Entity Framework,Linq,我正在尝试从列表中删除项目。它使用上述查询查找项目,但不会将其从列表中删除。我不知道为什么会这样 var qry = db.AssemblyListItems .AsNoTracking() .Where(x => x.ProductionPlanID == (long)_currentPlan.ProductionPlan) .ToList(); var hasbeenAssembled = db.Assembleds

我正在尝试从列表中删除项目。它使用上述查询查找项目,但不会将其从列表中删除。我不知道为什么会这样

var qry = db.AssemblyListItems
          .AsNoTracking()
          .Where(x => x.ProductionPlanID == (long)_currentPlan.ProductionPlan)
          .ToList();

var hasbeenAssembled = db.Assembleds
                       .AsNoTracking()
                       .Where(x => x.ProductionPlanId == (long)_currentPlan.ProductionPlan)
                       .ToList();


foreach (var item in hasbeenAssembled)
{
    qry = qry.RemoveAll(X => X.DocumentNo == item.DocumentId && 
                        X.ItemCode == item.KitHeaderId && 
                        X.ProductionPlanID == item.ProductionPlanId );
}

olvData.SetObjects(qry); 

上面是一个列表视图,我希望在其中显示项目。主查询“qry”位于顶部。

不要在查询结果中包含不需要的项。当数据库能够为您处理查询时,不要过早地从数据库中带来查询结果

var hasBeenAssembled = db.Assembleds
                       .AsNoTracking()
                       .Where(x => x.ProductionPlanId == (long)_currentPlan.ProductionPlan);

var qry = db.AssemblyListItems
          .AsNoTracking()
          .Where(x => x.ProductionPlanID == (long)_currentPlan.ProductionPlan)
          .Where(ali => !hasBeenAssembled.Any(hba => hba.DocumentId == ali.DocumentNo && hba.KitHeaderId == ali.ItemCode && hba.ProductionPlanId == ali.ProductionPlanID))
          .ToList();

olvData.SetObjects(qry); 

更容易做到这一点。第一个列表中的项目在第二个列表中不存在

from item in hasbeenAssembled
where !(qry.Any(X => X.DocumentNo == item.DocumentId && 
                        X.ItemCode == item.KitHeaderId && 
                        X.ProductionPlanID == item.ProductionPlanId))
select item;

通过从子查询的列表中排除组合项,可以在一次查询中处理此所有查询:

var productionPlan = (long)_currentPlan.ProductionPlan;
var qry = db.AssemblyListItems
    .AsNoTracking()
    .Where(item => item.ProductionPlanID == productionPlan
                && !db.Assembleds
                      .Any(x => x.ProductionPlanId == item.ProductionPlanID
                             && x.DocumentNo == item.DocumentId 
                             && x.ItemCode == item.KitHeaderId))

其优点是(正如其他人所说)不会将
AssemblyListItems
拉入内存,以后将再次丢弃。实体框架将能够将其转换为一条SQL语句,因此数据库可以有效地处理所有内容。

请阅读:当从列表中删除项时,I,J,K。当J是索引1,K是索引2时。K变为索引1,因此常规foreach将不起作用。您需要首先从列表末尾删除项目。因此,在LINQ中使用(i=hasbeenAssembled.Count-1;i>=0;i--){},而不是从
列表中删除项
,而是从查询的答案中排除项。@GertArnold
hasbeenAssembled
是直接在数据库上的
表达式;EF应该能够将其转换为SQL的一部分。LINQtoSQL没有问题,类似的查询会创建一个SQL查询。