/// <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 } }); }