Sam Jones
Sam Jones

Reputation: 4618

Querying Azure Table Storage with an expression

I'm looking to query table storage by passing an expression into my repository instead of a TableQuery, i'm aiming for this:

public async Task<IEnumerable<FiltersEntity>> Get(Expression<Func<FiltersEntity, bool>> query)
{  
    var table = _tableStorageConnector.CreateTableIfNotExists(_tableName);


    return await table.CreateQuery<FiltersEntity>().Where(query).ToList();
}

Ideal usage:

    var data = await _filterRepository.Get(x => x.PartitionKey.Equals("examplepartitionkey"));

I can't see any methods on CreateQuery or CreateQuery which accept an expression, only text.

I've also looked to see if I can convert the expression to filter text such as PartitionKey eq examplepartitionkey, but no luck.

Can someone please help me query azure table storage via expression?

The SDK i'm using is Microsoft.Azure.Cosmos.Table v1.0.7.0;

Upvotes: 1

Views: 7087

Answers (2)

jjhayter
jjhayter

Reputation: 390

Since Google and Bing can't seem to understand the difference with WATS vs Azure.Data.Tables I am leaving this example here for others searching for how to use the new SDK v12

    AsyncPageable<SimpleEntity> EventsQueryAsyncTask(CancellationToken ct)
    {
        var rowKeyStart = partition.EventVersionRowKey(startVersion);
        var rowKeyEnd = partition.EventVersionRowKey(startVersion + sliceSize - 1);

        var partitioned = partition.AsPartitionExpression<SimpleEntity>();

        var expression = partitioned.Body;
        var parameters = partitioned.Parameters[0]; // NOTE: use this if you have parameters to pass into your expression otherwise remove this variable...

        var lambda = Expression.Lambda<Func<SimpEntity, bool>>
        (
            Expression.AndAlso
            (
                expression,
                Query.WithinRangeAndLowerBoundEquality<SimpEntity>(rowKeyStart, rowKeyEnd).Body
            ),
            parameters // see comment above...
        );

        return client.QueryAsync
        (
            filter: lambda,
            maxPerPage: 100,
            select: null, // or pass in an IEnumerable<string> of columns you want to limit the projection to...
            cancellationToken: ct
        );
    }

Upvotes: 4

StuartLC
StuartLC

Reputation: 107387

Assuming using the Cosmos table driver against Azure Table Storage, you should be able to something along the lines of

public async Task<IEnumerable<MyTable>> MyQuery(Expression<Func<MyTable, bool>> predicate)
{
    var tableClient = new CloudTableClient(
        new Uri("..."),
        new StorageCredentials(".."));

    var table = tableClient.GetTableReference("MyTable");

    var tableQuery = table.CreateQuery<MyTable>()
        .Where(predicate)
        .AsTableQuery(); // << convert back from IQueryable to TableQuery

    var onePage = await table.ExecuteQuerySegmentedAsync(tableQuery, null);
    return onePage.Results;
}

Where MyTable implements ITableEntity and extends custom columns.

Note if the query is likely to return more than one page of data, then you'll need to replace the null with a TableContinuationToken and collect the pages in a loop.

I do agree that the number of, and guidance toward, client libraries for Azure Table storage is becoming quite frustrating.

Upvotes: 1

Related Questions