コード例 #1
0
        private async Task UpdateTable(DataTable dt)
        {
            if (!_resourcesMapping.ContainsKey(dt.TableName) || UpdatesPerformed.Contains(dt) || dt.Rows.Count == 0)
            {
                return;
            }

            var methodName = $"Update{dt.TableName}Async";

            // TODO handle the case of a write error on a batch of rows. Right now
            // the table is reported as not saved while in fact some rows might be saved
            // which would lead to inconsistency on the local Amica DB.

            foreach (DataRow row in dt.Rows)
            {
                await((Task)GetType().GetMethod(methodName).Invoke(this, new object[] { row, true }));
                if (ActionPerformed == ActionPerformed.Aborted)
                {
                    goto End;
                }
            }

            UpdatesPerformed.Add(dt);
            End :;
        }
コード例 #2
0
        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]);
            }
        }
コード例 #3
0
        /// <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);
            }
        }
コード例 #4
0
        /// <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);
        }