/// <summary>
        /// Queue a new operation
        /// </summary>
        /// <typeparam name="T">Type of businessObject</typeparam>
        /// <param name="businessObject">Business object instance - cannot be NULL.</param>
        /// <param name="type">Type of TableOperation to generate</param>
        public void Add <T>(T businessObject, TableOperationType type) where T : class
        {
            if (_isDraining)
            {
                // no items can be added during a drain
                throw new Exception("Cannot queue items during a drain.");
            }

            if (businessObject == null)
            {
                throw new ArgumentNullException("businessObject");
            }

            TableOperation operation = type switch
            {
                TableOperationType.Delete => TableOperation.Delete(AzureTableEntity.From(businessObject, forDelete: true)),
                TableOperationType.Insert => TableOperation.Insert(AzureTableEntity.From(businessObject)),
                TableOperationType.InsertOrMerge => TableOperation.InsertOrMerge(AzureTableEntity.From(businessObject)),
                TableOperationType.InsertOrReplace => TableOperation.InsertOrReplace(AzureTableEntity.From(businessObject)),
                TableOperationType.Merge => TableOperation.Merge(AzureTableEntity.From(businessObject)),
                TableOperationType.Replace => TableOperation.Replace(AzureTableEntity.From(businessObject)),
                _ => throw new ArgumentOutOfRangeException("Unsupported operation for queue!")
            };

            _queueOrder.Enqueue(_queueIndex);

            _queue.TryAdd(_queueIndex++, new TableOperationWrapper(operation, AzureTablesDataSource.GetTableName <T>()));
        }
Example #2
0
        /// <summary>
        /// Queue a new operation
        /// </summary>
        /// <typeparam name="T">Type of businessObject</typeparam>
        /// <param name="listOfObjects">Business object instances - cannot be NULL.</param>
        /// <param name="type">Type of TableBatchOperation to generate</param>
        public void Add <T>(IEnumerable <T> listOfObjects, TableOperationType type) where T : class
        {
            if (_isDraining)
            {
                // no items can be added during a drain
                throw new Exception("Cannot queue items during a drain.");
            }

            if (listOfObjects == null)
            {
                throw new ArgumentNullException(nameof(listOfObjects));
            }

            int t = (int)type;

            // these are the int values of the range of operation types supported
            if ((t < 0) || (t > 5))
            {
                throw new ArgumentOutOfRangeException("Unsupported operation for queue!");
            }

            string currentPartitionKey = Guid.NewGuid().ToString(); // nobody's partition key will ever be the same as this!
            string tableName           = AzureTablesDataSource.GetTableName <T>();
            string operationName       = Enum.GetName(typeof(TableOperationType), type) ?? "Unknown";

            TableBatchOperation batch = new TableBatchOperation();

            foreach (T obj in listOfObjects)
            {
                TableOperation tableOperation = type switch
                {
                    TableOperationType.Delete => TableOperation.Delete(AzureTableEntity.From(obj, forDelete: true)),
                    TableOperationType.Insert => TableOperation.Insert(AzureTableEntity.From(obj)),
                    TableOperationType.InsertOrMerge => TableOperation.InsertOrMerge(AzureTableEntity.From(obj)),
                    TableOperationType.InsertOrReplace => TableOperation.InsertOrReplace(AzureTableEntity.From(obj)),
                    TableOperationType.Merge => TableOperation.Merge(AzureTableEntity.From(obj)),
                    TableOperationType.Replace => TableOperation.Replace(AzureTableEntity.From(obj))

                    // Actually redundant, since this is already checked at the top of the function.
                    ,
                    _ => throw new ArgumentOutOfRangeException($"Unsupported operation '{operationName}'")
                };

                // all items in a batch must be the same partition key
                // so if we hit a different one, we jump to a new batch
                if ((batch.Count > 0) && (tableOperation.Entity.PartitionKey != currentPartitionKey))
                {
                    _queue.Enqueue(new TableBatchOperationWrapper(batch, tableName));

                    batch = new TableBatchOperation();
                    currentPartitionKey = tableOperation.Entity.PartitionKey;
                }
                else if (batch.Count == 0)
                {
                    currentPartitionKey = tableOperation.Entity.PartitionKey;
                }

                batch.Add(tableOperation);

                if (batch.Count == __MAX_ITEMS_PER_BATCH)
                {
                    _queue.Enqueue(new TableBatchOperationWrapper(batch, tableName));

                    batch = new TableBatchOperation();
                }

                ItemAdded?.Invoke(tableName, operationName, currentPartitionKey, tableOperation.Entity.RowKey);
            }

            // flush remaining entities to the queue
            if (batch.Count > 0)
            {
                _queue.Enqueue(new TableBatchOperationWrapper(batch, tableName));
            }
        }