如何使用Linq查询Azure存储表?

我不知道到底在哪里,但我对此有错误的想法。

我试图在第一个实例中使用linq查询azure存储表。 但我无法弄清楚它是如何完成的。 从各种来源看我有以下几点:

List blogs = new List(); CloudStorageAccount storageAccount = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("BlogConnectionString")); CloudTableClient tableClient = storageAccount.CreateCloudTableClient(); CloudTable blogTable = tableClient.GetTableReference("BlogEntries"); try { TableServiceContext tableServiceContext = tableClient.GetTableServiceContext(); TableServiceQuery query = (from blog in blogTable.CreateQuery() select blog).AsTableServiceQuery(tableServiceContext); foreach (BlogEntry blog in query) { blogs.Add(new BlogViewModel { Body = blog.Body }); } } catch { } 

在我搞砸之前,我可能已经把它靠近了。 要不然,或者我误解了TableService是什么。 以下代码对我有用,但我试图将其切换为使用Linq。

 List blogs = new List(); 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 lists; try { var query = new TableQuery(); 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’的定义,并且找不到接受类型为’System.Linq.IQueryable’的第一个参数的扩展方法’AsTableServiceQuery’(您是否缺少using指令或程序集引用?)

但是,我不认为这反映了真正的问题,我想我刚刚把它放错了,只是找不到任何有效的实例。

Azure存储客户端库的新表服务层中不再需要TableServiceContext。 有关此更改的更多信息,请参阅我们的博客文章Announcing Storage Client Library 2.1 RTM和CTP for Windows Phone 。

请确保BlogEntry实现ITableEntity ,然后以下代码应该可以正常工作:

 List blogs = new List(); CloudTableClient tableClient = storageAccount.CreateCloudTableClient(); CloudTable blogTable = tableClient.GetTableReference("BlogEntries"); try { IEnumerable query = (from blog in blogTable.CreateQuery() select blog); foreach (BlogEntry blog in query) { blogs.Add(new BlogViewModel { Body = blog.Body }); } } catch { } 

我当前的表存储库执行此操作:

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

我的_ cloudTable对应于你的blogTable

根据之前的回答,我创建了扩展方法来支持First, FirstOrDefault, Single and SingleOrDefault

 ///  /// Provides additional Linq support for the  class. ///  public static class LinqToTableQueryExtensions { ///  /// Returns the first element in a sequence. ///  /// The type of the elements of source. /// A TableQuery{TSource} to return the first element of public static TSource First(this TableQuery tableQuery) where TSource : ITableEntity { return ((IEnumerable)tableQuery.Take(1)).First(); } ///  /// Returns the first element in a sequence that satisfies a specified condition. ///  /// The type of the elements of source. /// A TableQuery{TSource} to return the first element of /// A function to test an element for a condition. public static TSource First(this TableQuery tableQuery, Expression> predicate) where TSource : ITableEntity { return tableQuery.Where(predicate).Take(1).First(); } ///  /// Returns the first element of the sequence or a default value if no such element is found. ///  /// The type of the elements of source. /// A TableQuery{TSource} to return the first element of public static TSource FirstOrDefault(this TableQuery tableQuery) where TSource : ITableEntity { return ((IEnumerable)tableQuery.Take(1)).FirstOrDefault(); } ///  /// Returns the first element of the sequence that satisfies a condition or a default value if no such element is found. ///  /// The type of the elements of source. /// A TableQuery{TSource} to return the first element of /// A function to test an element for a condition. public static TSource FirstOrDefault(this TableQuery tableQuery, Expression> predicate) where TSource : ITableEntity { return tableQuery.Where(predicate).Take(1).FirstOrDefault(); } ///  /// Return the only element of a sequence, and throws an exception if there is no exactly one element in the sequence. ///  /// The type of the elements of source. /// A TableQuery{TSource}> to return the single element of /// A function to test an element for a condition. public static TSource Single(this TableQuery tableQuery, Expression> predicate) where TSource : ITableEntity { // Get 2 and try to get single ^^ return tableQuery.Where(predicate).Take(2).Single(); } ///  /// 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. ///  /// The type of the elements of source. /// A TableQuery{TSource}> to return the single element of /// A function to test an element for a condition. public static TSource SingleOrDefault(this TableQuery tableQuery, Expression> 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() .Where(c => c.Email == "Walter1@contoso.com").First(); // Linq query that used the First() Extension method person = table.CreateQuery() .First(c => c.Email == "Walter1@contoso.com"); 

这里有一些方便的扩展方法来包装这个..(以及ServiceBus Custom Properties密钥库的奖金案例)

 namespace Microsoft.WindowsAzure.Storage.Table { public static class CloudTableExtensions { public static TEntity GetTableEntity(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(cloudTable, partitionKey, rowKey, requestOptions, operationContext); } public static TEntity GetTableEntity(this CloudTable cloudTable, string partitionKey, string rowKey, TableRequestOptions requestOptions = null, OperationContext operationContext = null) where TEntity : ITableEntity, new() { var singleInstanceQuery = (Expression>)(x => x.PartitionKey == partitionKey && x.RowKey == rowKey); IEnumerable queryResults = cloudTable.ExecuteQuery(singleInstanceQuery, requestOptions, operationContext); return queryResults.SingleOrDefault(); } public static IEnumerable ExecuteQuery(this CloudTable cloudTable, Expression> expression, TableRequestOptions requestOptions = null, OperationContext operationContext = null) where TEntity : ITableEntity, new() { var query = cloudTable.CreateQuery().Where(expression) as TableQuery; return cloudTable.ExecuteQuery(query, requestOptions, operationContext); } } }