skip to Main Content

I am trying to figure out what I can use instead of FirstOrDefault when trying to get a list of results from an EF database in one of my controller actions.

Basically, what I’m trying to do is whenever a work order is deleted, it loop through a ProductOrders table and edit the Quantity Available and Quantity on Hold amounts for all the records matching the ProductID‘s from that Order #, then delete the products from order.

My current controller action works perfectly deleting the the order, then deleting the products in ProductOrders with the same orderID, but the editing part I can only get it to edit the first product before deleting because of the FirstOrDefault. If I remove it, then I get an error

Cannot implicitly convert type System.Linq.IQueryable to MyProject.Models.ProductOrders

I’m still a newbie when it comes to this stuff and still don’t know the ins and outs of querying and making lists.

If I just want to do the product orders and was on the product orders page, this is simple and I wouldn’t have this issue, but it’s related to my work orders page when an order is deleted. So the id parameter passed is for the work order and not the product order.

For example, if I simply want to delete a product from an order and not an entire work order, in my controller action I can just do:

ProductOrder productOrder = db.ProductOrders.Find(id);

foreach (var item in db.ProductOrders.Where(x => x.ProductID == productOrder.ProductID).ToList())
{
    item.Qty_Available = available; //my specified value
    item.Qty_On_Hold = hold; //my specified value

    db.Entry(item).State = EntityState.Modified;

    db.SaveChanges();
}

and this will edit all the items that have that orderID value, but if I do that in the work order controller, the id parameter is for that model and the .Find(id) doesn’t get the value I need.

So I did a variable to get the list and it works fine, but I have to use FirstOrDefault to be able to link it to the product orders. So here is my current code that does everything I want it to do except for editing all the products within the order instead of just the first record from the FirstOrDefault

public ActionResult DeleteConfirmed(int id)
{
    WorkOrders workOrders = db.WorkOrders.Find(id);        
    var prod = db.ProductOrders.Where(p => p.OrderID == id);

    ProductOrder productOrder = prod.FirstOrDefault();

    var diff = productOrder.Qty_Ordered.Value - productOrder.Qty_Returned.Value;
    var available = productOrder.Qty_Available.Value + diff;
    var hold = productOrder.Qty_On_Hold.Value - diff;

    foreach (var item in db.ProductOrders.Where(x => x.ProductID == productOrder.ProductID).ToList())
    {
        item.Qty_Available = available;
        item.Qty_On_Hold = hold;

        db.Entry(item).State = EntityState.Modified;
        db.SaveChanges();
    }
        
    db.ProductOrders.RemoveRange(prod);
    db.WorkOrders.Remove(workOrders);
    db.SaveChanges();

    return RedirectToAction("ViewOrders");
}

Any help on how to get around this issue would be greatly appreciated. I’ve been stuck for a couple days now and ready to beat my head against the wall.

Most of the examples I’ve found on how to get all results instead of having to use FirstOrDefault have not been applicable to my scenario.

Thanks!

2

Answers


  1. Chosen as BEST ANSWER
        public ActionResult DeleteConfirmed(int id)
        {
            WorkOrders workOrders = db.WorkOrders.Find(id);
            var prod = db.ProductOrders.Where(p => p.OrderID == id);                            
    
            foreach (var po in prod.ToList())
            {
                var diff = po.Qty_Ordered.Value - po.Qty_Returned.Value;
                var available = po.Qty_Available.Value + diff;
                var hold = po.Qty_On_Hold.Value - diff;
    
                foreach(var item in db.ProductOrders.Where(p => p.ProductID == po.ProductID).ToList())
                {
                    item.Qty_Available = available;
                    item.Qty_On_Hold = hold;
                    db.Entry(item).State = EntityState.Modified;
                    db.SaveChanges();
                }
              
            }            
            db.ProductOrders.RemoveRange(prod);
            db.WorkOrders.Remove(workOrders);
            db.SaveChanges();
            return RedirectToAction("ViewOrders");
        }
    

    So I FINALLY got it working correctly! @wakasupi from your recommendation the extra foreach statement is what made the difference. I kept the workorders query and the var prod the same as my original code, but adding the extra foreach statement for the prod list allowed me to use that full query list instead of having to use firstordefault. Thank you all so much for the help, I've been stuck on this for around a week and was starting to get very irritated that I couldn't figure it out.


  2.         public ActionResult DeleteConfirmed(int id)
            {
                WorkOrders workOrders = db.WorkOrders.Find(id);
                var prod = db.ProductOrders.Where(p => p.OrderID == id);
                foreach (var po in prod.ToList())
                {
                    var diff = po.Qty_Ordered.Value - productOrder.Qty_Returned.Value;
                    var available = po.Qty_Available.Value + diff;
                    var hold = po.Qty_On_Hold.Value - diff;
    
                    foreach (var item in db.ProductOrders.Where(x => x.ProductID == po.ProductID))
                    {
                        item.Qty_Available = available;
                        item.Qty_On_Hold = hold;
                        db.Entry(item).State = EntityState.Modified;
                        db.SaveChanges();
                    }
            
                }
                db.ProductOrders.RemoveRange(workOrders.ProductOrders);
                db.WorkOrders.Remove(workOrders);
                db.SaveChanges();
                return RedirectToAction("ViewOrders");
            }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search