来自Azure表存储的TableQuery <t>,用于过滤分区键</t>

时间:2012-11-20 18:49:32

标签: c# azure azure-storage azure-table-storage

我正在试图通过partitionKey抽象来自Table的所有实体,如下所示:

public List<T> GetEntities<T>(string partitionKey, T entity) where T : TableEntity
    {
        try
        {
            var tableClient = _account.CreateCloudTableClient();
            var table = tableClient.GetTableReference(entity.GetType().Name.ToLower());
            var exQuery =
                new TableQuery<T>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal,
                                                                             partitionKey));

            var results = table.ExecuteQuery(exQuery).Select(ent => (T) ent).ToList();
            return results;
        }
        catch (StorageException ex)
        {
            //TODO: Add more trace info
            Trace.TraceInformation("Unable to retrieve entity based on query specs");
            return null;
        }
    }

但是,

失败了
new TableQuery<T>

因为TElement没有无参数构造函数。

3 个答案:

答案 0 :(得分:21)

正如您在问题中提到的,T必须具有无参数构造函数。因此,请按如下方式更改方法的定义:

public List<T> GetEntities<T>(string partitionKey, T entity) where T : TableEntity, new ()

答案 1 :(得分:7)

我为表存储编写了一个小的通用存储库:

 public class CloudTableRepository<T> where T : ITableEntity,new ()
{
    private readonly string _tableName;
    private CloudTable _table;

    public CloudTableRepository(string tableName)
    {
        _tableName = tableName;
        InitializeTable();
    }

    #region Public Methods

    public virtual async Task<List<T>> GetPartitionAsync(string partitionKey, int takeCount = 1000)
    {
        var result = new List<T>();
        var query =
            new TableQuery<T>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal,
                partitionKey));
        query.TakeCount = takeCount;
        TableContinuationToken tableContinuationToken = null;
        do
        {
            var queryResponse = await _table.ExecuteQuerySegmentedAsync(query, tableContinuationToken);
            tableContinuationToken = queryResponse.ContinuationToken;
            result.AddRange(queryResponse.Results);
        } while (tableContinuationToken != null);
        return result;
    }

    public virtual async Task<TableResult> GetSingleAsync(string partitionKey, string rowKey)
    {
       return  await GetSingle(partitionKey, rowKey);
    }

    public virtual async Task<T> UpdateAsync(T tableEntityData)
    {
        var updateCallistConfig = await GetSingleAsync(tableEntityData.PartitionKey, tableEntityData.RowKey);
        if (updateCallistConfig != null)
        {
            var updateOperation = TableOperation.InsertOrMerge(tableEntityData);
            var tableResult = await _table.ExecuteAsync(updateOperation);
            return (T) tableResult.Result;
        }
        return default(T);
    }

    public virtual async Task<T> AddAsync(T tableEntityData)
    {
        var retrieveOperation = TableOperation.Insert(tableEntityData);
        var tableResult = await _table.ExecuteAsync(retrieveOperation);
        return (T) tableResult.Result;
    }


    #endregion

    #region Private Methods

    private async void InitializeTable()
    {
        var storageAccount =
            CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting("TableStorageConnectionString"));
        var tableClient = storageAccount.CreateCloudTableClient();
        _table = tableClient.GetTableReference(_tableName);
        await _table.CreateIfNotExistsAsync();
    }

    private async Task<TableResult> GetSingle(string partitionKey, string rowKey)
    {
        var retrieveOperation = TableOperation.Retrieve<T>(partitionKey, rowKey);
        var tableResult = await _table.ExecuteAsync(retrieveOperation);
        return tableResult; //(T) tableResult.Result;
    }

    #endregion
}

答案 2 :(得分:2)

除了@ serdar-ozler-microsoft回答之外,你甚至不需要转换和转换实体来返回。

CloudTable.ExecuteQuery方法有一个接受泛型类型的重载:

public IEnumerable<TElement> ExecuteQuery<TElement>(
TableQuery<TElement> query,
TableRequestOptions requestOptions = null,
OperationContext operationContext = null)
where TElement : new(), ITableEntity

您还可以使用Linq过滤表服务。

这样你就可以像这样重写你的方法:

public List<T> GetEntities<T>(string partitionKey, T entity) where T : ITableEntity, new()
{
    try
    {
        var tableClient = _account.CreateCloudTableClient();
        var table = tableClient.GetTableReference(entity.GetType().Name.ToLower());
        return table.CreateQuery<T>().Where(e => e.PartitionKey == partitionKey).ToList();
    }
    catch (StorageException ex)
    {
        //TODO: Add more trace info
        Trace.TraceInformation("Unable to retrieve entity based on query specs");
        return null;
    }
}