wake-up-neo.com

Wie frage ich eine Azure-Speichertabelle mit Linq ab?

Ich bin mir nicht sicher, wo genau, aber ich habe irgendwo eine falsche Vorstellung davon.

Ich versuche zunächst, eine Azure-Speichertabelle mit linq abzufragen. Aber ich kann nicht herausfinden, wie es gemacht wird. Aus einer Vielzahl von Quellen habe ich Folgendes:

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 { }

Ich hatte es wahrscheinlich näher, bevor ich damit rumgespielt habe. Entweder das, oder ich verstehe falsch, was der TableService ist. Der folgende Code hat bei mir funktioniert, aber ich versuche, ihn auf Linq umzustellen.

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 { }

Ich konnte nirgendwo ein gutes solides Beispiel dafür finden, was ich tun sollte. Aber nach dem, was ich gelesen habe, ist es möglich, Linq zu verwenden. Jede Hilfe oder Hinweise geschätzt. Vielen Dank.


Leichtes Update. Das Folgende ist der Syntaxfehler, den ich derzeit bei AsTableServiceQuery erhalte:

'System.Linq.IQueryable' enthält keine Definition für 'AsTableServiceQuery' und es wurde keine Erweiterungsmethode 'AsTableServiceQuery' gefunden, die ein erstes Argument vom Typ 'System.Linq.IQueryable' akzeptiert (fehlt eine using-Direktive oder eine Assembly-Referenz?) ?)

Ich glaube jedoch nicht, dass dies das eigentliche Problem widerspiegelt. Ich glaube, ich habe es nur falsch zusammengestellt und kann nirgendwo ein solides Beispiel finden, das funktioniert.

15
AndrewPolland

TableServiceContext wird in der neuen Table Service-Schicht der Azure Storage Client Library nicht mehr benötigt. Weitere Informationen zu dieser Änderung finden Sie in unserem Blogbeitrag Ankündigung der Storage Client Library 2.1 RTM & CTP für Windows Phone .

Stellen Sie sicher, dass BlogEntry ITableEntity implementiert. Anschließend sollte der folgende Code einwandfrei funktionieren:

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

Mein aktuelles Tabellenspeicher-Repository führt dies aus:

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

Meine _cloudTable entspricht Ihrer blogTable.

15
Brendan Green

Basierend auf der vorherigen Antwort habe ich Erweiterungsmethoden erstellt, um First, FirstOrDefault, Single and SingleOrDefault zu unterstützen:

/// <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();
    }
}

So kannst du es so benutzen:

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

Im Folgenden finden Sie einige praktische Erweiterungsmethoden, mit denen Sie dies umwickeln können. (Und ein Bonusfall für den benutzerdefinierten ServiceBus-Eigenschaftenspeicher).

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