private async Task JSONArrayAppendAsync()

in Arriba/Arriba.Communication/Server/Application/ArribaImportApplication.cs [145:235]


        private async Task<IResponse> JSONArrayAppendAsync(IRequestContext ctx, Route route)
        {
            var content = ctx.Request.Headers["Content-Type"];

            if (String.IsNullOrEmpty(content) || !String.Equals(content, "application/json", StringComparison.OrdinalIgnoreCase))
            {
                return ArribaResponse.BadRequest("Content-Type of {0} was not expected", content);
            }
            else if (!ctx.Request.HasBody)
            {
                return ArribaResponse.BadRequest("Empty request body");
            }

            var tableName = GetAndValidateTableName(route);
            var table = this.Database[tableName];

            if (table == null)
            {
                return ArribaResponse.BadRequest("Table {0} is not loaded or does not exist", tableName);
            }

            var rows = await ctx.Request.ReadBodyAsync<List<Dictionary<string, object>>>();

            var detail = new
            {
                RequestSize = ctx.Request.Headers["Content-Length"],
                RowCount = rows.Count
            };

            using (ctx.Monitor(MonitorEventLevel.Information, "Import.JsonObjectArray", type: "Table", identity: tableName, detail: detail))
            {
                // Read column names from JSON
                var columnDetails = new Dictionary<string, ColumnDetails>();
                foreach (var row in rows)
                {
                    foreach (var property in row)
                    {
                        if (property.Value != null && !columnDetails.ContainsKey(property.Key))
                        {
                            var colDetail = new ColumnDetails(property.Key);
                            columnDetails.Add(property.Key, colDetail);
                        }
                    }
                }

                var columns = columnDetails.Values.ToArray();

                // Insert the data in batches 
                var block = new DataBlock(columns, BatchSize);
                for (int batchOffset = 0; batchOffset < rows.Count; batchOffset += BatchSize)
                {
                    int rowsLeft = rows.Count - batchOffset;
                    int rowsInBatch = BatchSize;

                    if (rowsLeft < BatchSize)
                    {
                        block = new DataBlock(columns, rowsLeft);
                        rowsInBatch = rowsLeft;
                    }

                    for (int blockRowIndex = 0; blockRowIndex < rowsInBatch; ++blockRowIndex)
                    {
                        int sourceRowIndex = blockRowIndex + batchOffset;

                        for (int columnIndex = 0; columnIndex < columns.Length; columnIndex++)
                        {
                            object value = null;

                            if (rows[sourceRowIndex].TryGetValue(columns[columnIndex].Name, out value))
                            {
                                block[blockRowIndex, columnIndex] = value;
                            }
                        }
                    }

                    table.AddOrUpdate(block, new AddOrUpdateOptions() { AddMissingColumns = true });
                }

                using (ctx.Monitor(MonitorEventLevel.Verbose, "table.save"))
                {
                    table.Save();
                }

                return ArribaResponse.Created(new ImportResponse
                {
                    TableName = table.Name,
                    RowCount = rows.Count(),
                    Columns = columns.Select((cd) => cd.Name).ToArray()
                });
            }
        }