Count table class
Inheritance: Microsoft.CTStore.Table
        /// <summary>
        /// Query count async
        /// </summary>
        /// <param name="table">Count table</param>
        /// <param name="partitionKey">Partition key for entity</param>
        /// <param name="countKey">Key for entity</param>
        /// <returns>Count entity for key</returns>
        public async Task <CountEntity> QueryCountAsync(CountTable table, string partitionKey, string countKey)
        {
            this.ValidateQueryCountParameters(table, partitionKey, countKey);
            switch (table.StorageMode)
            {
            case StorageMode.PersistentOnly:
                return(await this.persistentStore.QueryCountAsync(table, partitionKey, countKey));

            case StorageMode.CacheOnly:
                return(await this.cache.QueryCountAsync(table, partitionKey, countKey));

            case StorageMode.Default:
                CountEntity cacheEntity = await this.cache.QueryCountAsync(table, partitionKey, countKey);

                if (this.IsCacheEntityNullOrInvalid(cacheEntity))
                {
                    CountEntity persistentEntity = await this.persistentStore.QueryCountAsync(table, partitionKey, countKey);

                    Operation cachingOperation = this.GetCountCachingOperation(table, partitionKey, countKey, cacheEntity, persistentEntity);
                    await this.ExecuteCachingOperationAsync(cachingOperation);

                    return(persistentEntity);
                }

                return(cacheEntity);

            default:
                throw new NotSupportedException();
            }
        }
 /// <summary>
 /// Delete operation on count table
 /// </summary>
 /// <param name="table">Count table</param>
 /// <param name="partitionKey">Partition key for entity</param>
 /// <param name="countKey">Key for entity</param>
 /// <returns>Table operation</returns>
 public static Operation DeleteIfExists(CountTable table, string partitionKey, string countKey)
 {
     ValidateCountTableParameters(table, partitionKey, countKey);
     return(new Operation()
     {
         Table = table,
         OperationType = OperationType.DeleteIfExists,
         PartitionKey = partitionKey,
         Key = countKey
     });
 }
 /// <summary>
 /// Replace operation on count table
 /// </summary>
 /// <param name="table">Count table</param>
 /// <param name="partitionKey">Partition key</param>
 /// <param name="countKey">Key for entity</param>
 /// <param name="entity">Count entity</param>
 /// <returns>Table operation</returns>
 public static Operation Replace(CountTable table, string partitionKey, string countKey, CountEntity entity)
 {
     ValidateCountTableParameters(table, partitionKey, countKey, entity);
     return(new Operation()
     {
         Table = table,
         OperationType = OperationType.Replace,
         PartitionKey = partitionKey,
         Key = countKey,
         Entity = entity.Clone()
     });
 }
 /// <summary>
 /// Increment operation on count table
 /// </summary>
 /// <param name="table">Count table</param>
 /// <param name="partitionKey">Partition key for entity</param>
 /// <param name="countKey">Key for entity</param>
 /// <param name="value">Increment value</param>
 /// <returns>Table operation</returns>
 public static Operation Increment(CountTable table, string partitionKey, string countKey, double value = 1.0)
 {
     ValidateCountTableParameters(table, partitionKey, countKey);
     return(new Operation()
     {
         Table = table,
         OperationType = OperationType.Increment,
         PartitionKey = partitionKey,
         Key = countKey,
         Score = value
     });
 }
 /// <summary>
 /// Delete operation on count table
 /// </summary>
 /// <param name="table">Count table</param>
 /// <param name="partitionKey">Partition key for entity</param>
 /// <param name="countKey">Key for entity</param>
 /// <param name="entity">Count entity</param>
 /// <returns>Table operation</returns>
 public static Operation Delete(CountTable table, string partitionKey, string countKey, CountEntity entity = null)
 {
     ValidateCountTableParameters(table, partitionKey, countKey);
     return(new Operation()
     {
         Table = table,
         OperationType = OperationType.Delete,
         PartitionKey = partitionKey,
         Key = countKey,
         Entity = entity != null?entity.Clone() : null
     });
 }
        /// <summary>
        /// Query count async
        /// </summary>
        /// <param name="table">Count table</param>
        /// <param name="partitionKey">Partition key for entity</param>
        /// <param name="countKey">Key for entity</param>
        /// <returns>Count entity result. Returns null if entity does not exist</returns>
        public async Task <CountEntity> QueryCountAsync(CountTable table, string partitionKey, string countKey)
        {
            string      rowKey = this.GetRowKey(table, countKey);
            CountEntity entity = await this.QueryTableEntity <CountEntity>(table, partitionKey, rowKey);

            if (entity == null)
            {
                return(null);
            }

            entity.CountKey = countKey;
            return(entity);
        }
        /// <summary>
        /// Get increment and decrement operation for count table
        /// </summary>
        /// <param name="operation">Store operation</param>
        /// <param name="value">Value to add to counter</param>
        /// <returns>Table operation</returns>
        private async Task <TableOperation> GetCountTableOperation(Operation operation, double value)
        {
            string partitionKey = this.GetPartitionKey(operation);
            string rowKey       = this.GetRowKey(operation);

            CountTable  countTable = operation.Table as CountTable;
            CountEntity entity     = await this.QueryCountAsync(countTable, operation.PartitionKey, operation.Key);

            TableOperation tableOperation = null;

            if (entity != null)
            {
                entity.Count += value;

                // The following will generate a precondition failed exception if entity was updated
                // between the read and replace operation.
                Operation replaceOperation = Operation.Replace(countTable, operation.PartitionKey, operation.Key, entity);
                tableOperation = await this.GetTableOperation(replaceOperation);

                return(tableOperation);
            }

            if (operation.OperationType == OperationType.InsertOrIncrement)
            {
                // In case an entity gets added between the read and the following operation, it will generate
                // a conflict exception.
                Operation insertOperation = Operation.Insert(countTable, operation.PartitionKey, operation.Key, value);
                tableOperation = await this.GetTableOperation(insertOperation);

                return(tableOperation);
            }
            else
            {
                CountEntity replaceEntity = new CountEntity()
                {
                    Count = value,
                    ETag  = "W/\"datetime'2000-01-01T00%3A00%3A00.0000000Z'\"" // Dummy ETag Value
                };

                // We want to throw a not found exception. The following will throw a not found exception.
                // In case an entity gets added between the read and the following operation,
                // it will generate a precondition failed exception.
                // TODO: Need to make this consistent with cache.
                Operation replaceOperation = Operation.Replace(countTable, operation.PartitionKey, operation.Key, replaceEntity);
                tableOperation = await this.GetTableOperation(replaceOperation);

                return(tableOperation);
            }
        }
 /// <summary>
 /// Insert or replace operation on count table
 /// </summary>
 /// <param name="table">Count table</param>
 /// <param name="partitionKey">Partition key for entity</param>
 /// <param name="countKey">Key for entity</param>
 /// <param name="value">Initial value</param>
 /// <returns>Table operation</returns>
 public static Operation InsertOrReplace(CountTable table, string partitionKey, string countKey, double value)
 {
     ValidateCountTableParameters(table, partitionKey, countKey);
     return(new Operation()
     {
         Table = table,
         OperationType = OperationType.InsertOrReplace,
         PartitionKey = partitionKey,
         Key = countKey,
         Score = value,
         Entity = new CountEntity()
         {
             Count = value
         }
     });
 }