-1

I am trying to remove an item from a list. It finds the item with the above query, but it doesn't remove it from the list. I don't know why is it so?

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

Above is a listView where i want the items to appear. The main query "qry" is on the top.

its4zahoor
  • 1,709
  • 1
  • 16
  • 23
david
  • 87
  • 1
  • 9
  • Please read this: [Entity Framework .Remove() vs. .DeleteObject()](https://stackoverflow.com/questions/17723626/entity-framework-remove-vs-deleteobject) – Max Aug 13 '18 at 20:21
  • When removing items from a list I, J, K. When J is index 1 and K is index 2. K becomes index 1 so a regular foreach will not work. You need to remove items from the end of the list first. So use for(i = hasbeenAssembled.Count - 1; i >= 0; i--){} – jdweng Aug 13 '18 at 21:52
  • In LINQ, rather than remove items from a `List`, exclude Items from the answer of the query. – NetMage Aug 15 '18 at 01:15

3 Answers3

1

You can handle this all in one query by excluding the assembled items from the list in a subquery:

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

The advantage is (as also said by others) that you don't pull AssemblyListItems into memory that you're going to discard again later. Entity Framework will be able to translate this into one SQL statement, so everything is handled efficiently by he database.

Gert Arnold
  • 105,341
  • 31
  • 202
  • 291
0

Don't include the unwanted items in the results of the query. Don't prematurely bring over query results from the database when it might be able to process the query for you.

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); 
NetMage
  • 26,163
  • 3
  • 34
  • 55
  • @GertArnold `hasBeenAssembled` is an `Expression` directly on the database; EF should be able to translate it as part of the SQL. LINQ to SQL has no problem with it, a similar query creates one SQL query. – NetMage Aug 17 '18 at 00:00
0

Easier way to do this. Items in the first list does not exist in the second list.

from item in hasbeenAssembled
where !(qry.Any(X => X.DocumentNo == item.DocumentId && 
                        X.ItemCode == item.KitHeaderId && 
                        X.ProductionPlanID == item.ProductionPlanId))
select item;
Gauravsa
  • 6,330
  • 2
  • 21
  • 30