Я пытаюсь абстрагироваться от получения всех сущностей из таблицы через разделKey, например:
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 нет конструктора без параметров.
Ответ 1
Как вы упомянули в своем вопросе, T должен иметь конструктор без параметров. Следовательно, пожалуйста, измените определение своего метода следующим образом:
public List<T> GetEntities<T>(string partitionKey, T entity) where T : TableEntity, new ()
Ответ 2
Я написал небольшой общий репозиторий для хранения таблиц:
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
}
Ответ 3
В дополнение к ответу @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;
}
}