0

我正在使用 Cosmos DB Table API 来管理我的数据(使用 SQL API 不是一个选项)。我使用“创建日期时间刻度”作为“分区键”。这个想法是每半小时检索一次数据。为了得到半小时范围内的新数据,我写了一个方法,是这样的——(更新——基于 Gaurav 的建议,我已经更新了代码)。

public async Task<List<TEntity>> GetEntityWithDateTimePartitionKeyAsync<TEntity>(long startDateTimeTicks , long endDateTimeTicks, string tableName) where TEntity : TableEntity, new()
        {
            var results = new List<TEntity>();
            if (endDateTimeTicks > startDateTimeTicks)
            {
                var table = await this.GetTableAsync(tableName, true).ConfigureAwait(false);               
                 var filterA = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.GreaterThanOrEqual, startDateTimeTicks.ToString());
                 var filterB = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.LessThan, endDateTimeTicks.ToString());
                  var combinedFilter = TableQuery.CombineFilters(filterA, "AND", filterB);
                   var query = new TableQuery<TEntity>().Where(combinedFilter);         
              

                try
                {
                    results = table.ExecuteQuery<TEntity>(query).ToList();                   
                }
                catch(Exception ex)
                {
                }
            }
            return results;
        }

// Sample Data - 
public class TestItem: TableEntity
{
}

//Create the instances and then save them to Cosmos Db.
var testItem1 = new TestItem { PartitionKey ="637671350058032346",RowKey= "Mumbai", ETag="*" };
var testItem2 = new TestItem {PartitionKey = "637671350058033346", RowKey="Delhi" , ETag="*"};
var testItem3 = new TestItem { PartitionKey ="637671350058034346", RowKey="Chennai" , ETag="*"};
var testItem4 = new TestItem { PartitionKey ="637671350058035346", RowKey="Hyderabad" , ETag="*"}

//Calling the method -
var entityList = await GetEntityWithDateTimePartitionKeyAsync<TestItem>(637671350058030000 , 637671350058036000, "TestTable");

` 我遇到了一个异常 - “来自程序集 'Microsoft.Azure.Cosmos.Table, Version=1.0.8.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' 的 'QueryTokenVisitor' 类型中的方法 'Visit' 没有实现。”。我也尝试使用 LINQ 查询。但我无法让它工作。我尝试的另一件事是TableQuery.GenerateFilterCondition()。这适用于特定的“ PartitionKey ”和“ RowKey ”,但不适用于“PartitionKey”的范围。如何使用 Cosmos DB Table API 获取给定 DateTime 范围的结果?我是 Azure 表 API 的新手。

4

1 回答 1

0

您的代码存在一些问题:

  1. PartitionKey 是类型string,而您正在创建基于long. 您的过滤条件将导致 ODATA 查询,例如PartitionKey ge {startDateTimeTicks}Land PartitionKey lt {endDateTimeTicks}L。您需要使用如下代码:
var filterA = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.GreaterThanOrEqual, startDateTimeTicks.ToString());
var filterB = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.LessThan, endDateTimeTicks.ToString());
  1. 创建查询时,您缺少AND连接这两个过滤器的逻辑连接器(在您的情况下)。正因为如此,你的query样子PartitionKey lt {endDateTimeTicks}L(基本上它只是捡起来filterB)。您将需要结合这两个过滤条件并在查询中使用它:
var combinedFilter = TableQuery.CombineFilters(filterA, "AND", filterB);
var query = new TableQuery<DynamicTableEntity>().Where(combinedFilter);

当您这样做时,您的查询将如下所示:

(PartitionKey ge '{startDateTimeTicks}') AND (PartitionKey lt '{endDateTimeTicks}')

这个查询应该给你数据。

更新

我无法重现该问题。这是我使用的代码,它给了我正确的结果。

using System;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Table;
using Newtonsoft.Json;

namespace CosmosDbTableSamples
{
    class Program
    {
        static async Task Main(string[] args)
        {
            string accountName = "accountname";
            string accountKey =
                "accountkey";
            string tableUrl = "https://accountname.table.cosmos.azure.com:443/";
            string tableName = "Test";
            StorageCredentials credentials1 = new StorageCredentials();
            
            StorageCredentials credentials = new StorageCredentials(accountName, accountKey);
            CloudTableClient tableClient = new CloudTableClient(new Uri(tableUrl), credentials);
            CloudTable table = tableClient.GetTableReference(tableName);
            long startDateTimeTicks = 637671350058030000, endDateTimeTicks = 637671350058036000;
            var filterA = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.GreaterThanOrEqual, startDateTimeTicks.ToString());
            var filterB = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.LessThan, endDateTimeTicks.ToString());
            var combinedFilter = TableQuery.CombineFilters(filterA, "and", filterB);
            var query = new TableQuery<TestItem>().Where(combinedFilter);
            var result = await table.ExecuteQuerySegmentedAsync<TestItem>(query, null);
            foreach (var row in result)
            {
                Console.WriteLine($"{row.PartitionKey}|{row.RowKey}");
            }
        }
    }
    
    public class TestItem: TableEntity
    {
    }
}

我使用Microsoft.Azure.Cosmos.Table (1.0.8)了 SDK。

于 2021-09-09T02:23:31.513 回答