Created
October 16, 2019 09:03
-
-
Save springcomp/315c1ab7f1ef662487edc5fd5d2fcb66 to your computer and use it in GitHub Desktop.
Simple wrapper class for performing strongly-typed CRUD operations against an Azure Storage Table
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Threading.Tasks; | |
using Microsoft.Azure.Cosmos.Table; | |
using Microsoft.Extensions.Logging; | |
namespace SpringComp.TableStorage.Utils | |
{ | |
public class TableEntityStore<T> where T : TableEntity, new() | |
{ | |
private readonly string _connectionString; | |
private readonly string _tableName; | |
private CloudTable _cloudTable; | |
protected ILogger Logger { get; } | |
public TableEntityStore(string connectionString, string tableName, ILogger logger) | |
{ | |
_connectionString = connectionString; | |
_tableName = tableName; | |
Logger = logger; | |
} | |
protected internal async Task<CloudTable> InitTableAsync() | |
{ | |
if (_cloudTable != null) return _cloudTable; | |
var storageAccount = CloudStorageAccount.Parse(_connectionString); | |
var tableClient = storageAccount.CreateCloudTableClient(); | |
_cloudTable = tableClient.GetTableReference(_tableName); | |
await _cloudTable.CreateIfNotExistsAsync(); | |
return _cloudTable; | |
} | |
/// <summary> | |
/// Retrieves a single entity matching the specified index | |
/// </summary> | |
/// <param name="partitionKey"></param> | |
/// <param name="rowKey"></param> | |
/// <returns></returns> | |
public async Task<T> FindAsync(string partitionKey, string rowKey) | |
{ | |
await InitTableAsync(); | |
var query = new TableQuery<T> | |
{ | |
FilterString = LogicalAnd( | |
WhereEqual("PartitionKey", partitionKey), | |
WhereEqual("RowKey", rowKey)) | |
}; | |
var continuationToken = new TableContinuationToken(); | |
var page = await _cloudTable.ExecuteQuerySegmentedAsync(query, continuationToken); | |
return page?.Results.FirstOrDefault(); | |
} | |
/// <summary> | |
/// Retrieves all entities from the specified partition. | |
/// </summary> | |
/// <param name="partitionKey"></param> | |
/// <returns></returns> | |
public async IAsyncEnumerable<T> EnumAsync(string partitionKey) | |
{ | |
await InitTableAsync(); | |
var query = new TableQuery<T>(); | |
if (!string.IsNullOrEmpty(partitionKey)) | |
query.FilterString = WhereEqual("PartitionKey", partitionKey); | |
await foreach (var item in EnumAsync(query)) | |
yield return item; | |
} | |
public async IAsyncEnumerable<T> EnumAsync(TableQuery<T> query) | |
{ | |
if (query == null) | |
{ | |
throw new ArgumentException(nameof(query)); | |
} | |
var continuation = new TableContinuationToken(); | |
do | |
{ | |
var page = await _cloudTable.ExecuteQuerySegmentedAsync(query, continuation); | |
foreach (var result in page.Results) | |
yield return result; | |
continuation = page.ContinuationToken; | |
} while (continuation != null); | |
} | |
public async Task InsertAsync(T entity) | |
{ | |
await InitTableAsync(); | |
await _cloudTable.ExecuteAsync(TableOperation.InsertOrReplace(entity)); | |
} | |
public async Task DeleteAsync(string partitionKey, string rowKey, string eTag = "*") | |
{ | |
await InitTableAsync(); | |
await _cloudTable.ExecuteAsync(TableOperation.Delete(new DynamicTableEntity | |
{ | |
PartitionKey = partitionKey, | |
RowKey = rowKey, | |
ETag = eTag, | |
})); | |
} | |
public async Task DeleteAsync(T entity) | |
{ | |
await InitTableAsync(); | |
await _cloudTable.ExecuteAsync(TableOperation.Delete(entity)); | |
} | |
private static string WhereEqual(string property, string value) | |
{ | |
return TableQuery.GenerateFilterCondition(property, QueryComparisons.Equal, value); | |
} | |
private static string LogicalAnd(string left, string right) | |
{ | |
return TableQuery.CombineFilters(left, TableOperators.And, right); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment