public async Task UpdateAsync(DataSet dataSet) { var changes = dataSet.GetChanges(); if (changes == null) { return; } UpdatesPerformed.Clear(); var cache = new Dictionary <string, int>(); //foreach (var table in changes.Tables) //{ // var targetTable = (DataTable)table; // if (targetTable.Rows.Count == 0) continue; // //if (!_resourcesMapping.ContainsKey(targetTable.TableName)) continue; // UpdateParentTables(targetTable, 1, ref cache); // if (!cache.ContainsKey(targetTable.TableName)) // { // cache.Add(targetTable.TableName, 1); // } //} foreach (var tableName in _resourcesMapping.Keys) { if (!changes.Tables.Contains(tableName)) { continue; } var targetTable = changes.Tables[tableName]; if (targetTable.Rows.Count == 0) { continue; } UpdateParentTables(targetTable, 1, ref cache); if (!cache.ContainsKey(tableName)) { cache.Add(tableName, 1); } } var sortedCache = from entry in cache orderby entry.Value descending select entry; foreach (var c in sortedCache) { await UpdateTable(dataSet.Tables[c.Key]); } }
/// <summary> /// Casts a DataRow to the mathcing object supported by the server, then sends the object upstream for update. /// </summary> /// <typeparam name="T">Type to which the DataRow should be casted.</typeparam> /// <param name="row">DataRow to be sent to the server.</param> /// <param name="batch">Wether this update is part of a batch operation or not.</param> /// <returns></returns> private async Task UpdateRowAsync <T>(DataRow row, bool batch) where T : BaseModel { if (!batch) { UpdatesPerformed.Clear(); } await UpdateAsync <T>(row, batch); if (!batch) { UpdatesPerformed.Add(row.Table); } }
/// <summary> /// Casts a DataRow to the appropriate object tyoe and then stores it on a remote API endpoint. /// </summary> /// <typeparam name="T">Type to cast the DataRow to.</typeparam> /// <param name="row">DataRow to store.</param> /// <param name="batch">Wether this update is part of a batch operation or not.</param> /// <returns>T instance updated with API metadata, Or null if the operation was a delete.</returns> /// <remarks>The type of operation to be performed is inferred by DataRow's RowState property value.</remarks> private async Task <T> UpdateAsync <T>(DataRow row, bool batch) where T : BaseModel { ActionPerformed = ActionPerformed.NoAction; HttpResponse = null; // TODO this might be redundant as we have this guard in place already in both UpdateRowAsync and UpdateAsync(DataSet). if (!batch) { UpdatesPerformed.Clear(); } var targetRow = (row.RowState != DataRowState.Deleted) ? row : RetrieveDeletedRowValues(row); // 'cast' source DataRow into the corresponding object instance. object obj = Map.To <T>(targetRow); var shouldRetrieveRemoteCompanyId = (obj is BaseModelWithCompanyId); // retrieve remote meta field values from mapping datastore. var mapping = GetMapping(targetRow, shouldRetrieveRemoteCompanyId); if (mapping == null) { return(default(T)); } // and update corresponding properties. ((BaseModel)obj).UniqueId = mapping.RemoteId; ((BaseModel)obj).ETag = mapping.ETag; if (shouldRetrieveRemoteCompanyId) { ((BaseModelWithCompanyId)obj).CompanyId = mapping.RemoteCompanyId; } var retObj = default(T); RemoteRepositorySetup(); HttpStatusCode statusCode; ActionPerformed action; DelegateDbMethod dbMethod; switch (mapping.RemoteId) { case null: retObj = await _adam.Insert((T)obj); dbMethod = _db.Insert; action = ActionPerformed.Added; statusCode = HttpStatusCode.Created; break; default: switch (row.RowState) { case DataRowState.Modified: retObj = await _adam.Replace((T)obj); dbMethod = _db.Update; action = ActionPerformed.Modified; statusCode = HttpStatusCode.OK; break; case DataRowState.Deleted: await _adam.Delete((T)obj); dbMethod = _db.Delete; action = ActionPerformed.Deleted; statusCode = HttpStatusCode.NoContent; break; default: // TODO better exception.. or maybe just fail silently? throw new Exception("Cannot determine how the DataRow should be processed."); } break; } HttpResponse = _adam.HttpResponseMessage; ActionPerformed = (HttpResponse != null && HttpResponse.StatusCode == statusCode) ? action : ActionPerformed.Aborted; if (ActionPerformed != ActionPerformed.Aborted) { if (retObj != null) { // update mapping datatore with remote service meta fields. mapping.RemoteId = retObj.UniqueId; mapping.ETag = retObj.ETag; mapping.LastUpdated = retObj.Updated; } dbMethod(mapping); } return(retObj); }