简体   繁体   English

WCF数据服务BeginSaveChanges仅运行一次

[英]WCF Data Service BeginSaveChanges runs only once

I have the following WCF Data Service code in a Xamarin Forms application. 我在Xamarin Forms应用程序中具有以下WCF数据服务代码。 It updates a simple row in a table. 它更新表中的简单行。

    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);
         }            
     });

I have tested it on an emulator and a physical device. 我已经在模拟器和物理设备上对其进行了测试。

Sometimes it works perfectly . 有时它可以完美工作

Sometimes I get only these messages: 有时我只会收到以下消息:

  • Starting 开始
  • Getting the object 获取对象
  • Before the update 更新之前

Sometimes only these: 有时只有这些:

  • Starting 开始

It mostly gets wrong when I get a perfect update and I try again. 当我获得完美的更新时,大多数情况都会出错,然后重试。 Like it has 'used up' the only connection and after that it doesn't work. 就像它“用完”了唯一的连接,然后它就不起作用了。

On the server side I log every error and nothing is catched there. 在服务器端,我记录了每个错误,但没有发现任何错误。 Also, no exception on the client side. 同样,客户端也不例外。

The DataServiceContext MergeOption is set to PreserveChanges . DataServiceContext MergeOption设置为PreserveChanges

What could affect it? 有什么影响呢? When I send out a request, I have to wait some time? 当我发出请求时,我必须等待一段时间? Should I close the connection somehow? 我应该以某种方式关闭连接吗?

I reckon it is some kind of cache problem. 我认为这是某种缓存问题。

UPDATE : 更新

I tried again, with a simpler approach (I only save a new item now): 我再次尝试了一种更简单的方法(我现在只保存一个新项目):

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;
}

I also read (and it was pointed out in the first answer) that the result is provided on a different thread, so I added a dispatcher call to get the results (note the UI thread call: Xamarin.Forms.Device.BeginInvokeOnMainThread ). 我还阅读了 (在第一个答案中指出),结果是在另一个线程上提供的,因此我添加了一个调度程序调用以获取结果(请注意UI线程调用: Xamarin.Forms.Device.BeginInvokeOnMainThread )。

In an application where the callback must be invoked on a specific thread, you must explicitly marshal the execution of the End method, which handles the response, to the desired thread. 在必须在特定线程上调用回调的应用程序中,必须明确将End方法的执行编组到所需线程,该方法处理响应。 For example, in Windows Presentation Foundation (WPF)-based applications and Silverlight-based applications, the response must be marshaled back to the UI thread by using the BeginInvoke method on the Dispatcher object. 例如,在基于Windows Presentation Foundation(WPF)的应用程序和基于Silverlight的应用程序中,必须使用Dispatcher对象上的BeginInvoke方法将响应编组回UI线程。

Note the mentioning of the End method! 注意提到End方法!

I added the following debug message: 我添加了以下调试消息:

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

The result: 结果:

[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

It seems, that the context keeps gathering the objects but it sends only the first new object to the service and the other objects keep piling up. 上下文似乎一直在收集对象,但仅将第一个新对象发送到服务,而其他对象则在不断堆积。

The article emphasizes the thread issues of the End method, but the callback is the real issue here (it is not fired), so we never get to the End call and the UI thread. 本文着重介绍了End方法的线程问题,但是回调是此处的实际问题(未触发),因此我们永远也不会涉及End调用和UI线程。

This seems like a serious bug and I can't tell what to do... 这似乎是一个严重的错误,我不知道该怎么办...

The reason is that BeginExecute will start another thread, and your main thread returned even when the sub-thread doesn't finished. 原因是BeginExecute将启动另一个线程,并且即使子线程未完成,您的主线程也会返回。 Then this code may even not execute the BeginSaveChanges . 然后,此代码甚至可能不会执行BeginSaveChanges

So to make sure all the sub threads finished. 因此,请确保所有子线程完成。 The main thread need to wait for the sub threads. 主线程需要等待子线程。

The simplest way is to System.Threading.Thread.Sleep(5000) ; 最简单的方法是访问System.Threading.Thread.Sleep(5000) ; Or you can use IAsyncResult.AsyncWaitHandle.WaitOne() 或者,您可以使用IAsyncResult.AsyncWaitHandle.WaitOne()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM