0
votes

I have a form that allows the user to make changes to a widget, then enter a list of additional widgets that the same changes will be applied to. Using Entity Framework, I have the following working but it's slow and doesn't seem very efficient:

    //objectToSave: widgets - array of widgets to save changes to 
    //              pcram -   changes to apply to each widget
    public HttpResponseMessage PutPcram(ObjectToSave objectToSave)
    {
        if (!ModelState.IsValid)
        {
            return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
        }

        //loop through the widgets we want to save changes to
        for (var i = 0; i < objectToSave.widgets.Length; i++)
        {
            var e = db.PcramChanges.Find(objectToSave.widgets[i]);

            var excluded = new[] { "widgetID" };
            var x = db.Entry(e);
            foreach (var name in x.CurrentValues.PropertyNames.Except(excluded))
            {
                x.Property(name).IsModified = true;

                db.Entry(e).Property(name).CurrentValue = db.Entry(objectToSave.pcram).Property(name).CurrentValue;
            }                
        }

        try
        {
            db.SaveChanges();
        }
        catch (DbUpdateConcurrencyException ex)
        {
            return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
        }

        return Request.CreateResponse(HttpStatusCode.OK);            
    }

I basically want to save the changes made to the selected widget to multiple widgets and this was the only way I could come up with for excluding the "widgetID", which is the primary key. Any suggestions on how to improve this?

4

4 Answers

1
votes

I know I'm late, but what about ForEach?

objectToSave.widgets.ForEach(o => { o.Prop1 = Val1, o.Prop2 = Val2 });
Db.ObjectContext.SaveChanges();
0
votes

Entity Framework (at least up to EF5.0, may be in EF6.0 the situation had been changed) could not perform batch updates. It generates single query for each row update. I can suggest taking a look at EntityFramework.Extended library, which has extension methods, allowing performing batch update and batch delete.

0
votes

EF's change tracking engine is slow enough and it is fired on every property change.

If this is the reason in your case, try to wrap the cycle in

        db.Configuration.AutoDetectChangesEnabled = false;
        for (int i = 0; i < objectToSave.widgets.Length; i++)
        {
            // here is the logic
        }
        Db.ObjectContext.DetectChanges();
        Db.Configuration.AutoDetectChangesEnabled = true;
0
votes

You can try to do several operations in different threads, this is always way faster. Try to grab a group of widgets and do the changes in one thread. The other group of widgets in another thread and so on. The smaller the group is (more threads) it's probably faster until your pc says the opposite. See here, it's one way to do it.