WCF数据服务BeginSaveChanges只运行一次

时间:2015-03-18 12:48:24

标签: c# wcf-data-services xamarin.forms

我在Xamarin Forms应用程序中有以下WCF数据服务代码。 它更新表中的一个简单行。

    Static.Dialogs.Alert("Starting");
    DataServiceQuery<SRef.SimpleObject> query = (DataServiceQuery<SRef.SimpleObject>)Entities.SimpleObject.Where(x => x.ID == Guid.Parse("DEF47A0F-AF1E-4043-B8C8-56084841E80B"));
    query.BeginExecute((result) =>
             {
                 try
                 {
                     Static.Dialogs.Alert("Getting the object");
                     var actData = query.EndExecute(result).FirstOrDefault();
                     if (actData != null)
                     {
                         actData.Info = "Info"+randomNumber;
                         Entities.UpdateObject(actData);
                         Entities.ChangeState(actData, EntityStates.Modified);
                         Static.Dialogs.Alert("Before the update");
                         Entities.BeginSaveChanges(SaveChangesOptions.BatchWithIndependentOperations, (result2) =>
                         {
                             try
                             {
                                 Static.Dialogs.Alert("BeginSaveChanges starts");
                                 var r = Entities.EndSaveChanges(result2);
                                 Static.Dialogs.Alert("Update done ");
                             }
                             catch (Exception ex2)
                             {
                                 Static.Dialogs.Alert("Error:" + ex2.Message);
                             }
                         }, null);
                     }
                     else
                         Static.Dialogs.Alert("No object");
                 }
                 catch (Exception ex1)
                 {
                     Static.Dialogs.Alert("Error:" + ex1.Message);
                 }
             }, null);
         }
         catch (Exception ex)
         {
             Static.Dialogs.Alert("Error:" + ex.Message);
         }            
     });

我已在模拟器和物理设备上测试过它。

有时它完全

有时我只收到这些消息:

  • 启动
  • 获取对象
  • 更新前

有时只有这些:

  • 启动

当我得到一个完美的更新并且我再试一次时,它大多会出错。就像它已经用完了#39;唯一的联系,之后它不起作用。

在服务器端,我记录每个错误,没有任何东西被捕获。此外,客户端也不例外。

DataServiceContext MergeOption设置为 PreserveChanges

有什么可能影响它?当我发出请求时,我要等一段时间?我应该以某种方式关闭连接吗?

我认为这是 某种缓存问题。

更新

我再次尝试,采用更简单的方法(我现在只保存一个新项目):

private DataServiceReference.DataEntities entities;

public DataServiceReference.DataEntities Entities
{
  get
  {
    if (entities == null)
    {
      entities = new DataServiceReference.DataEntities(Static.BaseURI);
      entities.MergeOption = MergeOption.OverwriteChanges;
      entities.SaveChangesDefaultOptions = SaveChangesOptions.ReplaceOnUpdate;
    }
    return entities;
  }
}

var newItem = new DataServiceReference.Info()
{
  Name = "Name " + DateTime.Now.Second,
  ID = Guid.NewGuid(),
  Role = "1"
};
Entities.AddToInfo(newItem);
try
{
  foreach (var item in Entities.Entities)
  {
    System.Diagnostics.Debug.WriteLine(item.Identity + " " + item.State);
  }
  var res = Entities.BeginSaveChanges(SaveChangesOptions.Batch,
      (result) =>
      {
        //var s = 3; //debug point - only hit once
        try
        {
          //back to the UI thread
          Xamarin.Forms.Device.BeginInvokeOnMainThread(() =>
          //(result.AsyncState as DataServiceReference.DataEntities).EndSaveChanges(result));
             Entities.EndSaveChanges(result));
        }
        catch (Exception ex)
        {
          System.Diagnostics.Debug.WriteLine(ex.Message);
          throw;
        }
      }, Entities);
  //res.AsyncWaitHandle.WaitOne(1000); //it only blocks the main thread, no use

  resultList.Add(newItem.Name);
}
catch (Exception ex2)
{
   System.Diagnostics.Debug.WriteLine(ex2.Message);
   throw;
}

我也read(并在第一个答案中指出)结果是在不同的线程上提供的,所以我添加了一个调度程序调用来获取结果(注意UI线程调用:{{ 1}})。

  

在必须针对特定内容调用回调的应用程序中   线程,你必须显式编组End方法的执行,   它处理响应,到所需的线程。例如,在   基于Windows Presentation Foundation(WPF)的应用程序和   基于Silverlight的应用程序,响应必须被整理回来   在Dispatcher上使用BeginInvoke方法的UI线程   对象

请注意提及Xamarin.Forms.Device.BeginInvokeOnMainThread方法!

我添加了以下调试消息:

End

结果:

foreach (var item in Entities.Entities)
{
  System.Diagnostics.Debug.WriteLine(item.Identity + " " + item.State);
}

看起来,上下文不断收集对象,但它只向服务发送第一个新对象,而其他对象不断堆积。

本文强调[0:]http://192.168.1.100/InfoDataService/InfoDataService.svc/Info(guid'f1057131-90ee-11d7-9812-0040f6cc1384') Unchanged [0:]http://192.168.1.100/InfoDataService/InfoDataService.svc/Info(guid'f1057133-90ee-11d7-9812-0040f6cc1384') Unchanged [0:]http://192.168.1.100/InfoDataService/InfoDataService.svc/Info(guid'f6cfce91-90ef-11d7-9812-0040f6cc1384') Unchanged [0:]http://192.168.1.100/InfoDataService/InfoDataService.svc/Info(guid'a6c2d822-91a7-11d7-9813-0040f6cc1384') Unchanged [0:]http://192.168.1.100/InfoDataService/InfoDataService.svc/Info(guid'a6c2d823-91a7-11d7-9813-0040f6cc1384') Unchanged [0:]http://192.168.1.100/InfoDataService/InfoDataService.svc/Info(guid'a6c2d824-91a7-11d7-9813-0040f6cc1384') Unchanged [0:]http://192.168.1.100/InfoDataService/InfoDataService.svc/Info(guid'b750e561-91b8-11d7-9813-0040f6cc1384') Unchanged [0:]http://192.168.1.100/InfoDataService/InfoDataService.svc/Info(guid'b750e562-91b8-11d7-9813-0040f6cc1384') Unchanged [0:]http://192.168.1.100/InfoDataService/InfoDataService.svc/Info(guid'b750e563-91b8-11d7-9813-0040f6cc1384') Unchanged [0:]http://192.168.1.100/InfoDataService/InfoDataService.svc/Info(guid'eee2d1f7-17cb-4283-a053-01f6cf7bb2fd') Unchanged [0:] Added [0:] Added [0:] Added 方法的线程问题,但回调是真正的问题(它没有被触发),所以我们永远不会到{{1}调用和UI线程。

这似乎是一个严重的错误,我不知道该怎么做......

1 个答案:

答案 0 :(得分:0)

原因是BeginExecute将启动另一个线程,即使子线程未完成,您的主线程也会返回。那么这段代码甚至可能不会执行BeginSaveChanges

所以要确保所有子线程完成。主线程需要等待子线程。

最简单的方法是System.Threading.Thread.Sleep(5000);或者您可以使用IAsyncResult.AsyncWaitHandle.WaitOne()