我不确定到底在哪里,但我在某处发现了错误的想法。
我试图在第一个实例中使用linq查询azure存储表。但我无法弄清楚它是如何完成的。通过查看各种来源,我有以下内容:
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上的语法错误:
&#39; System.Linq.IQueryable&#39;不包含&#39; AsTableServiceQuery&#39;的定义没有扩展方法&#39; AsTableServiceQuery&#39;接受类型为'System.Linq.IQueryable&#39;的第一个参数;可以找到(你错过了使用指令或程序集引用吗?)
然而,我并不认为这反映了真正的问题,我认为我把它放在一起是错误的,只是无法找到一个有效的例子。
答案 0 :(得分:26)
Azure存储客户端库的新表服务层中不再需要TableServiceContext。有关此更改的详细信息,请参阅我们的博文Announcing Storage Client Library 2.1 RTM & CTP for 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 { }
答案 1 :(得分:15)
我当前的表存储库执行此操作:
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
。
答案 2 :(得分:1)
根据之前的回答,我已经创建了支持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 == "Walter1@contoso.com").First();
// Linq query that used the First() Extension method
person = table.CreateQuery<CustomerEntity>()
.First(c => c.Email == "Walter1@contoso.com");
答案 3 :(得分:0)
这里有一些方便的扩展方法来包装它.. (以及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);
}
}
}