I have access to an OData v3 service. I know about a particular data table named “Persons” in the service and I have the URI ending with “Persons” to access that table. I know that this table contains a few instances of a particular class named “Customer”. I know the properties defined in this class, for example “FirstName”, “LastName”, “SysModifiedOn”. I am trying to load data from this data table and to modify one of these instances and save this modification into the OData service.
In my Visual Studio project in Service References I have a reference to the OData service, named “MyService”. I can access the “MyService” class, which inherits from the “System.Data.Services.Client.DataServiceContext” class. My colleague told me that I should use the “BeginExecute” method referencing a callback method calling the “EndExecute” method to retrieve items from the service, and the “BeginSaveChanges” and “EndSaveChanges” methods to save the modifications. I tried this code to load data from the “Persons” table in the service, to modify one item and to update it in the service. I call the “CreateConnection” method.
private MyService.Model client;
private ObservableCollection<Customer> customers;
private void CreateConnection()
{
this.client = new Model(new Uri("http://.../.../odata.v3/default"));
this.LoadCustomers();
}
private void LoadCustomers()
{
if (this.customers == null)
{
this.customers = new ObservableCollection<Customer>();
}
this.customers.Clear();
try
{
var query = this.client.CreateQuery<Customer>("Persons");
var results = query.BeginExecute(this.OnCustomersQueryComplete, query);
}
catch (Exception ex)
{
}
}
private void OnCustomersQueryComplete(IAsyncResult result)
{
var query = (System.Data.Services.Client.DataServiceQuery<Customer>)result.AsyncState;
Customer toModify = null;
try
{
foreach (Customer c in query.EndExecute(result))
{
this.customers.Add(c);
this.Status += Environment.NewLine + string.Format("loaded object: [{0}.{1}] {2} {3}", c.SysModifiedOn.ToString(), c.SysModifiedOn.Millisecond.ToString("000"), c.FirstName, c.LastName);
if (c.FirstName.StartsWith("John"))
{
toModify = c;
}
}
}
catch (Exception ex)
{
}
if (toModify != null)
{
toModify.FirstName = "Johnny";
toModify.SysModifiedOn = DateTime.Now;
this.SaveChanges(toModify);
}
else
{
this.Status += Environment.NewLine + "Nothing to modify.";
}
}
private void SaveChanges(object o)
{
this.Status += Environment.NewLine + "Updating…";
this.client.UpdateObject(o);
this.client.SaveChangesDefaultOptions = System.Data.Services.Client.SaveChangesOptions.PatchOnUpdate;
IAsyncResult result = this.client.BeginSaveChanges(this.OnClientSaveChanges, this.client);
}
private void OnClientSaveChanges(IAsyncResult result)
{
this.Status += Environment.NewLine + "Update started!";
this.client.EndSaveChanges(result);
this.Status += Environment.NewLine + "Updated!";
}
This code is a part of my ViewModel, which has a string property “Status”, which is displayed in the user interface through binding.
If I put this code into a Xamarin.Forms application and I call the “CreateConnection” method, I see the list of items loaded from the service, then the “Updating…” message and nothing more. Apparently, the “OnClientSaveChanges” method is not invoked. Please, can you help me find out what prevents the saving process from completing?
In a Windows application (for example Console application), however, the code completes and the modification is saved in the OData service. I need the same to work in a Xamarin.Forms application.