it-swarm.com.ru

Как запросить таблицу хранения Azure с помощью Linq?

Я не уверен, где именно, но у меня есть неправильное представление где-то с этим.

Сначала я пытаюсь запросить таблицу хранения Azure с помощью linq. Но я не могу понять, как это делается. Из просмотра различных источников у меня есть следующее:

List<BlogViewModel> blogs = new List<BlogViewModel>();

CloudStorageAccount storageAccount = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("BlogConnectionString"));
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
CloudTable blogTable = tableClient.GetTableReference("BlogEntries");

try
{
   TableServiceContext tableServiceContext = tableClient.GetTableServiceContext();
   TableServiceQuery<BlogEntry> query = (from blog in blogTable.CreateQuery<BlogEntry>()
   select blog).AsTableServiceQuery<BlogEntry>(tableServiceContext);
   foreach (BlogEntry blog in query)
   {
      blogs.Add(new BlogViewModel { Body = blog.Body });
   }
}
catch { }

У меня, вероятно, было это ближе, прежде чем я возился с этим. Либо так, либо я неправильно понимаю, что такое TableService. Следующий код работал для меня, но я пытаюсь переключить его на использование Linq.

List<BlogViewModel> blogs = new List<BlogViewModel>();

var storageAccount = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("BlogConnectionString"));
var tableClient = storageAccount.CreateCloudTableClient();
CloudTable blogTable = tableClient.GetTableReference("BlogEntries");

TableRequestOptions reqOptions = new TableRequestOptions()
{
   MaximumExecutionTime = TimeSpan.FromSeconds(1.5),
   RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(3), 3)
};
List<BlogEntry> lists;

try
{
   var query = new TableQuery<BlogEntry>();
   lists = blogTable.ExecuteQuery(query, reqOptions).ToList();

   foreach (BlogEntry blog in lists)
   {
      blogs.Add(new BlogViewModel { Body = blog.Body });
   }
}
catch { }

Мне нигде не удалось найти хороший солидный пример того, что я должен делать. Но из того, что я читал, можно предположить, что использование Linq возможно. Любая помощь или указатели приветствуются. Благодарю.


Небольшое обновление. Ниже приведена синтаксическая ошибка, которую я сейчас получаю от AsTableServiceQuery:

System.Linq.IQueryable не содержит определения для AsTableServiceQuery и не может быть найден метод расширения «AsTableServiceQuery», принимающий первый аргумент типа «System.Linq.IQueryable» (если вы пропустили директиву using или ссылку на сборку ?)

Тем не менее, я не думаю, что это отражает реальную проблему, я думаю, что я все неправильно понял, просто не могу найти надежного примера, где бы он ни работал.

15
AndrewPolland

TableServiceContext больше не требуется в новом уровне службы таблиц клиентской библиотеки хранилища Azure. Подробнее об этом изменении см. В нашем блоге Объявление о клиентской библиотеке хранилища 2.1 RTM и CTP для Windows Phone .

Убедитесь, что BlogEntry реализует ITableEntity , и тогда следующий код должен работать просто отлично:

List<BlogViewModel> blogs = new List<BlogViewModel>();

CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
CloudTable blogTable = tableClient.GetTableReference("BlogEntries");

try
{
    IEnumerable<BlogEntry> query = (from blog in blogTable.CreateQuery<BlogEntry>()
                                    select blog);
    foreach (BlogEntry blog in query)
    {
        blogs.Add(new BlogViewModel { Body = blog.Body });
    }
}
catch { }
24
Serdar Ozler

Мой текущий репозиторий хранения таблиц делает это:

public IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> expression) 
{
    if (IsTableEmpty())
    {
        return Enumerable.Empty<TEntity>().AsQueryable();
    }
    else
    {
        return _cloudTable.CreateQuery<TEntity>().AsQueryable().Where(expression);
    }
}

Мой _cloudTable соответствует вашему blogTable.

15
Brendan Green

Основываясь на предыдущем ответе, я создал методы расширений для поддержки First, FirstOrDefault, Single and SingleOrDefault:

/// <summary>
/// Provides additional Linq support for the <see cref="TableQuery{TElement}"/> class. 
/// </summary>
public static class LinqToTableQueryExtensions
{
    /// <summary>
    /// Returns the first element in a sequence.
    /// </summary>
    /// <typeparam name="TSource">The type of the elements of source.</typeparam>
    /// <param name="tableQuery">A TableQuery{TSource} to return the first element of</param>
    public static TSource First<TSource>(this TableQuery<TSource> tableQuery) where TSource : ITableEntity
    {
        return ((IEnumerable<TSource>)tableQuery.Take(1)).First();
    }

    /// <summary>
    /// Returns the first element in a sequence that satisfies a specified condition.
    /// </summary>
    /// <typeparam name="TSource">The type of the elements of source.</typeparam>
    /// <param name="tableQuery">A TableQuery{TSource} to return the first element of</param>
    /// <param name="predicate">A function to test an element for a condition.</param>
    public static TSource First<TSource>(this TableQuery<TSource> tableQuery, Expression<Func<TSource, bool>> predicate) where TSource : ITableEntity
    {
        return tableQuery.Where(predicate).Take(1).First();
    }

    /// <summary>
    /// Returns the first element of the sequence or a default value if no such element is found.
    /// </summary>
    /// <typeparam name="TSource">The type of the elements of source.</typeparam>
    /// <param name="tableQuery">A TableQuery{TSource} to return the first element of</param>
    public static TSource FirstOrDefault<TSource>(this TableQuery<TSource> tableQuery) where TSource : ITableEntity
    {
        return ((IEnumerable<TSource>)tableQuery.Take(1)).FirstOrDefault();
    }

    /// <summary>
    /// Returns the first element of the sequence that satisfies a condition or a default value if no such element is found.
    /// </summary>
    /// <typeparam name="TSource">The type of the elements of source.</typeparam>
    /// <param name="tableQuery">A TableQuery{TSource} to return the first element of</param>
    /// <param name="predicate">A function to test an element for a condition.</param>
    public static TSource FirstOrDefault<TSource>(this TableQuery<TSource> tableQuery, Expression<Func<TSource, bool>> predicate) where TSource : ITableEntity
    {
        return tableQuery.Where(predicate).Take(1).FirstOrDefault();
    }

    /// <summary>
    /// Return the only element of a sequence, and throws an exception if there is no exactly one element in the sequence.
    /// </summary>
    /// <typeparam name="TSource">The type of the elements of source.</typeparam>
    /// <param name="tableQuery">A TableQuery{TSource}> to return the single element of</param>
    /// <param name="predicate">A function to test an element for a condition.</param>
    public static TSource Single<TSource>(this TableQuery<TSource> tableQuery, Expression<Func<TSource, bool>> predicate) where TSource : ITableEntity
    {
        // Get 2 and try to get single ^^
        return tableQuery.Where(predicate).Take(2).Single();
    }

    /// <summary>
    /// Returns the only element of a sequence, or a default value if the sequence is empty; this method throws an exception if there is more than one element in the sequence.
    /// </summary>
    /// <typeparam name="TSource">The type of the elements of source.</typeparam>
    /// <param name="tableQuery">A TableQuery{TSource}> to return the single element of</param>
    /// <param name="predicate">A function to test an element for a condition.</param>
    public static TSource SingleOrDefault<TSource>(this TableQuery<TSource> tableQuery, Expression<Func<TSource, bool>> predicate) where TSource : ITableEntity
    {
        // Get 2 and try to get single ^^
        return tableQuery.Where(predicate).Take(2).SingleOrDefault();
    }
}

Так что вы можете использовать это так:

public class CustomerEntity : TableEntity { public string Email { get; set; } } 
...
var storageAccount = CloudStorageAccount.Parse( "MyStorageAccountConnectionstring");
var tableClient = storageAccount.CreateCloudTableClient();
var table = tableClient.GetTableReference("myTable");

// Linq Query with Where And First
var person = table.CreateQuery<CustomerEntity>()
    .Where(c => c.Email == "[email protected]").First();

// Linq query that used the First() Extension method
person = table.CreateQuery<CustomerEntity>()
    .First(c => c.Email == "[email protected]");
1
Thomas

Вот несколько удобных методов расширения, чтобы обернуть это .. (И бонусный случай для хранилища ключей пользовательских свойств ServiceBus)

namespace Microsoft.WindowsAzure.Storage.Table
{
    public static class CloudTableExtensions
    {
        public static TEntity GetTableEntity<TEntity>(this CloudTable cloudTable, BrokeredMessage brokeredMessage, string partitionKeyPropertyName, string rowKeyPropertyName, TableRequestOptions requestOptions = null, OperationContext operationContext = null)
            where TEntity : ITableEntity, new()
        {
            var partitionKey = brokeredMessage.Properties[partitionKeyPropertyName] as string;
            var rowKey = brokeredMessage.Properties[rowKeyPropertyName] as string;
            return GetTableEntity<TEntity>(cloudTable, partitionKey, rowKey, requestOptions, operationContext);
        }

        public static TEntity GetTableEntity<TEntity>(this CloudTable cloudTable, string partitionKey, string rowKey, TableRequestOptions requestOptions = null, OperationContext operationContext = null)
            where TEntity : ITableEntity, new()
        {
            var singleInstanceQuery = (Expression<Func<TEntity, bool>>)(x => x.PartitionKey == partitionKey && x.RowKey == rowKey);
            IEnumerable<TEntity> queryResults = cloudTable.ExecuteQuery(singleInstanceQuery, requestOptions, operationContext);
            return queryResults.SingleOrDefault();
        }

        public static IEnumerable<TEntity> ExecuteQuery<TEntity>(this CloudTable cloudTable, Expression<Func<TEntity, bool>> expression, TableRequestOptions requestOptions = null, OperationContext operationContext = null)
            where TEntity : ITableEntity, new()
        {
            var query = cloudTable.CreateQuery<TEntity>().Where(expression) as TableQuery<TEntity>;
            return cloudTable.ExecuteQuery(query, requestOptions, operationContext);
        }
    }
}
0
JoeBrockhaus