Updating records in foreach loop in Entity Framework 6

10,309

As discussed in the comments, since Entity Framework context is (internally) employing the Unit of Work pattern, you need to call SaveChanges() only once and only after you've done modifying all the items.

More on MSDN

Share:
10,309
Piotr Truszkowski
Author by

Piotr Truszkowski

Updated on June 04, 2022

Comments

  • Piotr Truszkowski
    Piotr Truszkowski almost 2 years

    I have a problem with updating records in a foreach loop. I have a method that exports files from SQL Table and saves them on a net share:

        public static void SyncOpportunity()
        {
            using (var ctx = new BPMOnline74Entities())
            {
                logger.Debug("Importing files from Opportunities.");
                var oppFiles = from o in ctx.OpportunityFile
                               where SqlFunctions.DataLength(o.Data) > 0 && o.ServiceProcessed == false
                               select o;
    
                foreach (OpportunityFile opp in oppFiles)
                {
                    logger.Debug(string.Format("{0} is being imported.", opp.Name));
                    string fileName="";
                    if (opp.OpportunityId == null)
                    {
                        fileName = "E:\\BPM\\Opportunity\\";
                        logger.Error("File not bound to any DB object. Saved in E:\\BPM\\Opportunity.");
                    }
                    else
                    {
                        try
                        {
                            fileName = PathInfo.GetPath("Opportunity", (Guid)opp.OpportunityId);
                        }
                        catch (Exception ex)
                        {
                            logger.Error(ex.Message.ToString());
                        }
                    }
                    try
                    {
                        File.WriteAllBytes(fileName + opp.Name, opp.Data);
                        logger.Debug(string.Format("{0} was exported from SQL.", opp.Name));
                        opp.ServiceProcessed = true;
                        ctx.Entry(opp).State = System.Data.Entity.EntityState.Modified;
                        ctx.SaveChanges();
                    }
                    catch(Exception ex)
                    {
                        logger.Error(ex.Message.ToString());
                    }
                }
                logger.Debug(string.Format("Imported {0} files.", oppFiles.Count().ToString()));
            }
            logger.Debug("Disposing SyncOpportunity.");
        }
    

    After the file is successfully exported from SQL I want to update the record's "ServiceProcessed" field to true so it won't be selected on the next iteration of my service. The problem is that my method doesn't update the DB and always "catches" all of my records.