19

I'm porting my existing class library that targets .NET Framework 4.6.2 to .NET Core 1.1.

Looks like some of the methods that are available in .NET Framework version are not there in .NET Core. Two such methods are table.CreateQuery and table.ExecuteQuery.

Here's an existing function that's giving me an error for CreateQuery:

public T Get<T>(string partitionKey, string rowKey, string tableName) where T : ITableEntity, new()
            => getTable(tableName).CreateQuery<T>().Where(r => r.PartitionKey == partitionKey && r.RowKey == rowKey).FirstOrDefault();

How do I create query in .NET Core?

Ian Kemp
  • 28,293
  • 19
  • 112
  • 138
Sam
  • 26,817
  • 58
  • 206
  • 383

2 Answers2

20

According to this question: Missing syncronous methods for dotnet core?,NetCore/Netstandard support does not yet include Sync implementation of the APIs.

Since CreateQuery and ExecuteQuery are all Sync method, so we couldn’t use it in .NET Core, you could only use ExecuteQuerySegmentedAsync,TableQuery, Fluent API and handle the continuation token it returns. More details, you could refer to follow codes:


Update:

public static void Main(string[] args)
{
    var result = Get<BookTest3>("Aut_Fantasy", "Cert-0000000020", "DifferenetPartitionTest");
    Console.Write(result.PartitionKey);
    Console.Read();
}

public static T Get<T>(string partitionKey, string rowKey, string tableName) where T : ITableEntity, new()
{
    CloudTable table = ConnectToTable(tableName);
    TableQuery<T> employeeQuery = new TableQuery<T>().Where(
        TableQuery.CombineFilters(
            TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey),
            TableOperators.And,
            TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.LessThan, rowKey))
        ).Take(1);
    var re = new T();
        TableContinuationToken continuationToken = null;
    do
    {
        Task<TableQuerySegment<T>> employees = table.ExecuteQuerySegmentedAsync(employeeQuery, continuationToken);
        TableQuerySegment<T> employeess = employees.Result;
        re= employeess.FirstOrDefault();
        continuationToken = employeess.ContinuationToken;
    } while (continuationToken != null);
    return re;
}

Hope this could give you some tips.


Update code:

public static void Main(string[] args)
{
    var tas = Get<BookTest3>("Aut_Fantasy", "Cert-0000000020", "DifferenetPartitionTest");
    var result = tas.Result;
    Console.Write(result.PartitionKey);
    Console.Read();
}

public async static Task<T> Get<T>(string partitionKey, string rowKey, string tableName) where T : ITableEntity, new()
{
    //new T();
    CloudTable table = ConnectToTable(tableName);
    TableQuery<T> employeeQuery = new TableQuery<T>().Where(
        TableQuery.CombineFilters(
            TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionKey),
            TableOperators.And,
            TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.LessThan, rowKey))
        ).Take(1);
    var re = new T();
        TableContinuationToken continuationToken = null;
    do
    {
        var employees = await table.ExecuteQuerySegmentedAsync(employeeQuery, continuationToken);

        re = employees.FirstOrDefault();
        continuationToken = employees.ContinuationToken;
    } while (continuationToken != null);
    return re;
}
Max Weber
  • 95
  • 5
Brando Zhang
  • 22,586
  • 6
  • 37
  • 65
  • How do I make my method generic so that I can read any entity i.e. Get, not just BookTest3? I've been looking for some examples for this everywhere but I couldn't find it. The GET method in my code must be useable in any scenario -- meaning it should be able to return any object type. – Sam Mar 23 '17 at 01:14
  • Thank you. I really appreciate it. I don't think the first line `new T();` is necessary in the Get method, is it? – Sam Mar 23 '17 at 04:51
  • I have one more question, if I may. Even though we're making an asynchronous call with `ExecuteQuerySegmentedAsync()`, we don't use `await` inside the method or `async Task` in the method header. My business layer methods that calls the `Get` method are usually `async` methods so it feels a bit awkward NOT to call the `Get` with an `await` even though we're making an asynchronous call inside it. – Sam Mar 24 '17 at 05:53
  • As far as I know, we could also use the async Task in the method header and use the await in the method content, it is as same as my codes, just changed a little codes. – Brando Zhang Mar 24 '17 at 09:15
  • how can we do the querying wiht linq? – Alex Gordon Jan 24 '19 at 16:54
  • According to https://azure.microsoft.com/pl-pl/resources/samples/azure-cosmos-db-table-dotnet-getting-started/ go with Microsoft.Azure.CosmosDB.Table NuGet as it's the one supporting CosmosDB and Azure Tables – Voodu Aug 16 '19 at 15:46
11

I'll tack these handy extension methods on to this post :)

public static async System.Threading.Tasks.Task<IEnumerable<DynamicTableEntity>> ExecuteQueryAsync(this CloudTable table, TableQuery query)
{
    TableContinuationToken token = null;
    var retVal = new List<DynamicTableEntity>();
    do
    {
        var results = await table.ExecuteQuerySegmentedAsync(query, token);
        retVal.AddRange(results.Results);
        token = results.ContinuationToken;
    } while (token != null);

    return retVal;
}

public static async System.Threading.Tasks.Task<IEnumerable<T>> ExecuteQueryAsync<T>(this CloudTable table, TableQuery<T> query) where T : ITableEntity, new()
{
    TableContinuationToken token = null;
    var retVal = new List<T>();
    do
    {
        var results = await table.ExecuteQuerySegmentedAsync(query, token);
        retVal.AddRange(results.Results);
        token = results.ContinuationToken;
    } while (token != null);

    return retVal;
}

They give you back the same functionality but with ExecuteQueryASYNC as the method name

bc3tech
  • 1,228
  • 14
  • 27