locked
can not refresh data in context with "OverwriteChanges" (wcf data services Mar11 ctp, EF 4.1) RRS feed

  • Question

  • I have the following function that I call to refresh the data in the context after calling savechanges, but it does not work:

    		

    publicvoid GetMonthlyInputData(DateTime date, District district, Metal metal, Action<ObservableCollection<MonthlyInput>> cb)         { ObservableCollection<MonthlyInput> o = newObservableCollection<MonthlyInput>(); _reconEntitiesSVC.MergeOption = MergeOption.OverwriteChanges; DataServiceQuery<MonthlyInput> dsq = (DataServiceQuery<MonthlyInput>) (from mi in _reconEntitiesSVC     .CreateQuery<MonthlyInput>("MonthlyInputs") .Expand("District, Metal, MonthlyValues, MonthlyValues/ProjectName")  where mi.Year == date.Year && mi.Month == date.Month && mi.Metal.Name == metal.Name && mi.District.Name == district.Name  select mi ); dsq.BeginExecute( (ar) => //the callback of this asyc query { Deployment.Current.Dispatcher.BeginInvoke(() => //put on UI thread { DataServiceQuery<MonthlyInput> qr = ar.AsyncState asDataServiceQuery<MonthlyInput>; if (qr != null) { IEnumerable<MonthlyInput> res = qr.EndExecute(ar); res.ToList().ForEach(o.Add); } //return the resultsif (cb != null) cb(o); }); }, dsq); //the query }


       

    If I kill the context and create a new one then all the changes posted to the db via savechanges shows up.

    What is the problem?

    I have seen others use "OverwriteChanges" to refresh the context. Creating a new context each time I call

    SaveChanges is out of the question. Why isn't this working?

    Furthermore, it seems to be an issue with deleting an object. I have the following:

            public void RemoveReconValue(MonthlyInput monthlyInputData, ReconValue rv, Action cb)
            {
                if (rv == null || rv.ProjectName == null || monthlyInputData==null)
                    return;
     
    		_reconEntitiesSVC.DeleteLink(monthlyInputData, "MonthlyValues", rv);
    		_reconEntitiesSVC.UpdateObject(monthlyInputData);
                	_reconEntitiesSVC.DeleteObject(rv);
                	SaveChangesToDB(cb);
            }
    

    If I call RemoveReconValue() and then call GetMonthlyData() the rv that was deleted is still there in the context.

    If I free the context and get a new one then the rv that was deleted is gone. I need to be able to delete an entity

    without having to get a new context as many items are tied to a Silverlight UI and freeing the context causes all

    those entities to stop being tracked.

    Why Doesn't overwritechanges refresh the context with actual data from the DB?

    Alternatively, I tried using Loadproperty and that did the same thing as my query. The context is not getting

    updated from the DB. How to force that?


    zapper


    • Edited by doczap Tuesday, April 10, 2012 4:45 AM
    Monday, April 9, 2012 4:41 PM

Answers

  • So the following seems to work:

            public void RemoveReconValue(MonthlyInput monthlyInputData, ReconValue rv, Action cb)
            {
                if (rv == null || rv.ProjectName == null || monthlyInputData==null)
                    return;
     
    		_reconEntitiesSVC.DeleteLink(monthlyInputData, "MonthlyValues", rv);
            	monthlyInputData.MonthlyValues.Remove(rv);
    		_reconEntitiesSVC.UpdateObject(monthlyInputData);
                	_reconEntitiesSVC.DeleteObject(rv);
                	SaveChangesToDB(cb);
            }
    

    So, just calling DeleteObject() is not enough. An entity has to be manually removed from any entities that it might be linked to. I am starting to

    dislike WCF Data Services. It needs some syntactic sugar to hide all of these details, which are otherwise, too hard to remember.


    zapper

    • Marked as answer by doczap Tuesday, April 10, 2012 7:04 AM
    Tuesday, April 10, 2012 5:50 AM

All replies

  • Hi,

    I think MergeOption is something you set before calling SaveChanges, not after.

    MergeOption alters the way the framework will auto refresh the client copy of tracked entities after saving changes.

    I think that if you set the MergeOption before the call to SaveChanges, then you won't need your refresh logic at all.

    Uffe

    Tuesday, April 10, 2012 4:55 AM
  • Thanks for your input Uffe. I just tried what you suggested and it did not work. Here is my savechanges code:

            private void SaveChangesToDB(Action cb)
            {
    		_reconEntitiesSVC.MergeOption = MergeOption.OverwriteChanges; //suggested by Uffe
    		//push changes to db
            	_reconEntitiesSVC.BeginSaveChanges(SaveChangesOptions.ReplaceOnUpdate, ar =>
                    {
                        Deployment.Current.Dispatcher.BeginInvoke(() => //put on UI thread
                        {
                            try
                            {
    	                        var res = _reconEntitiesSVC.EndSaveChanges(ar);
                            }
                            catch (Exception ex)
    			{
    			#region some exception handling stuff for debugging
    			#endregion
                            }
                            cb();
                        });
                    }, null);
            }
    

    The DB gets updated but the context is not. This is very frustrating.


    zapper


    • Edited by doczap Tuesday, April 10, 2012 5:02 AM
    Tuesday, April 10, 2012 5:01 AM
  • Hi,

    The documentation states that you need to set the mergeoption prior to doing any queries or updates. This is from MSDN...

    "Set this property to the appropriate materialization option before executing any queries or updates to the data service."

    Does it work if you set it immediately after creating the context?

    Uffe

    Tuesday, April 10, 2012 5:41 AM
  • Hi,

    The documentation states that you need to set the mergeoption prior to doing any queries or updates. This is from MSDN...

    "Set this property to the appropriate materialization option before executing any queries or updates to the data service."

    Does it work if you set it immediately after creating the context?

    Uffe

    No.

    zapper

    Tuesday, April 10, 2012 5:44 AM
  • So the following seems to work:

            public void RemoveReconValue(MonthlyInput monthlyInputData, ReconValue rv, Action cb)
            {
                if (rv == null || rv.ProjectName == null || monthlyInputData==null)
                    return;
     
    		_reconEntitiesSVC.DeleteLink(monthlyInputData, "MonthlyValues", rv);
            	monthlyInputData.MonthlyValues.Remove(rv);
    		_reconEntitiesSVC.UpdateObject(monthlyInputData);
                	_reconEntitiesSVC.DeleteObject(rv);
                	SaveChangesToDB(cb);
            }
    

    So, just calling DeleteObject() is not enough. An entity has to be manually removed from any entities that it might be linked to. I am starting to

    dislike WCF Data Services. It needs some syntactic sugar to hide all of these details, which are otherwise, too hard to remember.


    zapper

    • Marked as answer by doczap Tuesday, April 10, 2012 7:04 AM
    Tuesday, April 10, 2012 5:50 AM