简体   繁体   中英

What package should I use for Azure Tables when migrating away from "WindowsAzure.Storage"

I am currently migrating a project that was written for .NET Fx 4.8 using ASP.NET WebApi to .NET 5.0. This project makes heavy use of the package WindowsAzure.Storage for accessing BLOBs, tables and queues on a Azure Storage account. This package has been deprecated for a while now, stating that is has been split up into several packages.

For Queues and Blobs it is quite clear what I should migrate to. But there seems to be a lot of confusion regarding Azure Tables however.

  • First of all in the NuGet package WindowsAzure.Storage it states that the package to use for tables would be Microsoft.Azure.CosmosDB.Table . It's a bit confusing because I always thought that "CosmosDB" is something entirely different than "Azure Tables", but maybe I am wrong.
  • The description of Microsoft.Azure.CosmosDB.Table however states that this package is in maintenance mode and will be deprecated. I should use Microsoft.Azure.Cosmos.Table instead.
  • Microsoft.Azure.Cosmos.Table however has not been updated for ages and 2.0.0 is in preview for more than two years now. There is also an issue on its GitHub repo that specifically asks if this project is dead - with no answer.
  • After searching around, I found the package Azure.Data.Tables to be closest to what I might be looking for. It's updated, looks alive and seems in line (version-number wise) with the other storage packages. Only the naming is a bit off. There's also a blog post from MS in June this year talking about this package being brand new and all, so I guess this is what I was looking for?

Anyway: I found the API of Azure.Data.Tables quite similar to WindowsAzure.Storage , I just had to make a few tweaks here and there.

But what I am totally missing now is the classes QueryComparisons and TableQuery . Are they just gone? Is there are replacement?

An example of the code to migrate would be:

var part1 = 
  TableQuery.GenerateFilterConditionForGuid(
    nameof(SomeEntity.Id),
    QueryComparisons.Equal,
    idValue));
var part2 = 
  TableQuery.GenerateFilterConditionForGuid(
    nameof(SomeEntity.Category)
    QueryComparisons.Equal,
    category));
return TableQuery.CombineFilters(part1, TableOperators.And, part2);

I came across the same problem. Yes, TableQuery from Microsoft.Azure.Cosmos.Tables is gone, and the references in documentation to TableOdataFilter are useless as it doesn't exist.

Looking at this, I found the easiest way to query Azure Storage Tables using the Azure.Data.Tables package is to use the .Query<T>([predicate]) method . eg

TableClient customers;

var example = customers.Query<Customer>(c => c.Name == "Microsoft");

There is also a .QueryAsync<T>(..) async version.

If you were building queries with the TableQuery there is no direct alternative, but you can use something like PredicateBuilder to combine .And() and .Or() expressions to create the predicate.

I modified this to create a fluent version:

    /// <summary>
    /// Helper class to build predicates fluently
    /// </summary>
    /// <remarks>
    /// Adapted from source: http://www.albahari.com/nutshell/predicatebuilder.aspx
    /// </remarks>
    public class PredicateBuilder<T>
    {
        private Expression<Func<T, bool>> expression;

        /// <summary>
        /// Add an OR clause
        /// </summary>
        /// <param name="expr">new expression</param>
        /// <returns></returns>
        public PredicateBuilder<T> Or(Expression<Func<T, bool>> expr)
        {
            if (expression == null)
                expression = expr;
            else
            {
                var invokedExpr = Expression.Invoke(expr, expression.Parameters.Cast<Expression>());
                expression = Expression.Lambda<Func<T, bool>>(Expression.OrElse(expression.Body, invokedExpr), expression.Parameters);
            }
            return this;
        }

        /// <summary>
        /// Add an AND clause
        /// </summary>
        /// <param name="expr">new expression</param>
        /// <returns></returns>
        public PredicateBuilder<T> And(Expression<Func<T, bool>> expr)
        {
            if (expression is null)
                expression = expr;
            else
            {
                var invokedExpr = Expression.Invoke(expr, expression.Parameters.Cast<Expression>());
                expression = Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expression.Body, invokedExpr), expression.Parameters);
            }
            return this;
        }

        /// <summary>
        /// Return resulting expression
        /// </summary>
        /// <returns></returns>
        public Expression<Func<T, bool>> ToPredicate()
        {
            if (expression is null)
                return (T value) => true;
            return expression;
        }
    }

Example usage:

var query = new PredicateBuilder<Customer>();

if(name != null)
  query.And(c => c.Name == name);

if (isActive == false)
  query.And(c => c.IsActive == false);

Hope this helps

You should probably have read a little further in that blog post and the related docs :

Querying Table Entities

The TableClient allows the user to create custom queries using OData filters.

string MyPK = "markers";
string MyRK = "id-001";
string filter = TableOdataFilter.Create($"PartitionKey eq {MyPK} or RowKey eq {MyRK}")

Pageable<TableEntity> entities = tableClient.Query<TableEntity>(filter: filter);

foreach (TableEntity entity in entities)
{
    Console.WriteLine($"{entity.GetString("Product")}: {entity.GetInteger("Count")}");
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM