we are develoipng a windows phone 8 app which get datas from a .NET WebService. We have to check from a big records list which one has been modified or deleted and pass it back to the app. At the moment records are more than 46000; i explain:
our Windows phone's app performs this call:
private const int HUGE_OPERATION_TIMEOUT_MINUTES = 10;
public static Task<GetCustomersCompletedEventArgs> GetClientiAsyncTask(this GridwaySoapClient client,
Guid AuthenticationToken, DateTime LastUpdate,
int i, string jsonEntityKeyList)
{
var tcs = new TaskCompletionSource<GetCustomersCompletedEventArgs>();
client.Endpoint.Address = WsAddress();
client.Endpoint.Binding.ReceiveTimeout = new TimeSpan(0, HUGE_OPERATION_TIMEOUT_MINUTES, 0);
client.Endpoint.Binding.OpenTimeout = new TimeSpan(0, HUGE_OPERATION_TIMEOUT_MINUTES, 0);
client.Endpoint.Binding.CloseTimeout = new TimeSpan(0, HUGE_OPERATION_TIMEOUT_MINUTES, 0);
client.Endpoint.Binding.SendTimeout = new TimeSpan(0, HUGE_OPERATION_TIMEOUT_MINUTES, 0);
client.InnerChannel.OperationTimeout = new TimeSpan(0, HUGE_OPERATION_TIMEOUT_MINUTES, 0);
client.GetCustomersCompleted += (s, e) => TransferCompletion<GetCustomersCompletedEventArgs>(tcs, e, () => e);
try
{
client.OpenAsync();
client.GetCustomersAsync(AuthenticationToken, LastUpdate, jsonEntityKeyList, string.Empty, i);
}
catch (Exception ex)
{
throw ex;
}
return tcs.Task;
}
GetCustomersAsync invokes another method which calls for WS passing a list of IDs; those IDs are checked on the database with the script below.
this is what we do:
- we pass a list of ids from app, which are the ids of records already passed
- db check, by getting all record's id on db, if the ids passed are still in this list
WS passes back a new list of ids which are the ones deleted or edited from db
[WebMethod(BufferResponse = false)] public string GetCustomers(Guid AuthenticationToken, DateTime LastUpdate, string jsonEntityKeyList, ref string jsonDeleteKeyList, int chiamataNumero) { List<CUSTOMER> customers = new List<CUSTOMER>(); if (GridwayAuthenticationToken.Exist(AuthenticationToken)) { List<string> EntityKeyList = JsonConvert.DeserializeObject<List<string>>(jsonEntityKeyList); var crmCtx01 = new CrmGridwayAdapter().GetXrmServiceContext(); // if it's the first time we don't ned to remove anything from app // 01/01/1900 is the defauld date used if there's no lastUpdate's date if (LastUpdate == null || LastUpdate == new DateTime(1900, 01, 01)) { List<Account> clienti = new List<Account>(); try { clienti = crmCtx01.AccountSet.Skip(chiamataNumero * 500).Take(500).ToList(); } catch { return Serializer.Serialize(customers); } var clientiToPick = clienti.Where(x => !EntityKeyList.Contains(x.Id.ToString())).ToList(); if (clientiToPick.Count == 0 && clienti.Count > 0) { List<CUSTOMER> fake = new List<CUSTOMER>(); CUSTOMER fakeS = null; fake.Add(fakeS); return Serializer.Serialize(fake); } if (clientiToPick != null) { customers = clientiToPick.Select(x => new CUSTOMER() { ID = (Guid)x.AccountId, FULL_NAME = x.Name, PHONE_NO = x.Telephone1, PIVA_CF = x.new_piva, MODIFIED_ON = (x.ModifiedOn == null ? CRMMinDate() : Convert.ToDateTime(x.ModifiedOn)) }).ToList(); } } //if it's not the first time we sync there might be datas on app else { //we do this step only the first time if (chiamataNumero == 0 && EntityKeyList.Count() > 0) { try { // THIS is the step stopping connection List<string> customersId = crmCtx01.AccountSet .Select(x => x.AccountId.ToString()).ToList(); List<string> noMoreExistingRecords = EntityKeyList.Where(x => !customersId.Contains(x)).ToList(); List<string> editedRecords = crmCtx01.AccountSet.Where(x => x.ModifiedOn > LastUpdate).Select(x => x.AccountId.ToString()).ToList(); List<string> AddressCessatiIds = crmCtx01.AccountSet.Where(x => x.StateCode != 0).Select(x => x.AccountId.ToString()).ToList(); noMoreExistingRecords.AddRange(editedRecords); noMoreExistingRecords.AddRange(AddressCessatiIds); EntityKeyList.RemoveAll(x => editedRecords.Contains(x)); jsonDeleteKeyList = Serializer.Serialize(noMoreExistingRecords); } catch (Exception ex) { } } List<Account> clienti = new List<Account>(); try { clienti = crmCtx01.AccountSet.Where(x => x.ModifiedOn > LastUpdate).Skip(chiamataNumero * 500).Take(500).ToList(); } catch { return Serializer.Serialize(customers); } var clientiToPick = clienti.Where(x => !EntityKeyList.Contains(x.Id.ToString())).ToList(); if (clientiToPick.Count == 0 && clienti.Count > 0) { List<CUSTOMER> fake = new List<CUSTOMER>(); CUSTOMER fakeS = null; fake.Add(fakeS); return Serializer.Serialize(fake); } if (clientiToPick != null) { customers = clientiToPick.Select(x => new CUSTOMER() { ID = (Guid)x.AccountId, FULL_NAME = x.Name, PHONE_NO = x.Telephone1, PIVA_CF = x.new_piva, MODIFIED_ON = (x.ModifiedOn == null ? CRMMinDate() : Convert.ToDateTime(x.ModifiedOn)) }).ToList(); } } return Serializer.Serialize(customers); } else { throw GridwayAuthenticationToken.AuthenticationExceptions.AuthenticationRequired(); } }
so: this code doesn't perform only the call i'm saying but also a call to give to the app the records which haven't been downloaded yet. we had the same problem with them so we had to pass 500 records each time and we solved the connection lost's problem; it's slow but it works.
We can't do this for ids, we pass them all and we can't check if a list of more than 46000 records contains 500 without having all 4600 records..
Anyone can help? we don't know how to solve it