CosmosDB LINQQuery 和 ContinuationToken 问题

问题描述 投票:0回答:1

我在使用 LINQ 执行 CosmosDb 查询时遇到问题。当我添加 ORDER BY 子句同时删除它时,主要问题出现了,查询运行顺利。添加 ORDER BY 子句使得查询的第二次迭代,当我添加 continuationToken 时,抛出异常。 这是 continuationToken (我删除了该令牌,因为它很长):

[
    {
        "compositeToken": {
        "token":"+RID:~njgzAO5qBgzIGQAAAAAACA...",
            "range": {
                "min": "",
                "max": "05C1E0"
            }
        },
        "orderByItems": [
            {
                "item": 74.80897
            }
        ],
        "rid": "njgzAO5qBgzIGQAAAAAACA==",
        "skipCount": 0,
        "filter": "true"
    }
]

这是来自异常的消息:

响应状态码不表示成功:BadRequest(400);子状态:0;活动ID:5a692073-43db-4050-a856-d3d7cae01503;原因: ({"errors":[{"severity":"Error","location":{"start":245,"end":246},"code":"SC1001","message":"语法错误,',' 附近的语法不正确。"}]} ActivityId:5a692073-43db-4050-a856-d3d7cae01503、Microsoft.Azure.Cosmos.Tracing.TraceData.ClientSideRequestStatisticsTraceDatum、Windows/10.0.22621 cosmos-netstandard-sdk/3.31.4);

下面是我用于 vreatin tyhe IQuerable 的方法:

private async Task<IQueryable<TDatabase>> _GetQuery(Expression<Func<T, bool>> predicate, Expression<Func<T, object>> orderByExpression, bool disc, TDatabase s, PagedItem pagedItem = null, Expression<Func<T, object>> orderThenByExpressionPaged = null, bool pagedDesc = false)
{
    await Task.CompletedTask;
    var queryDefinition = container.GetItemLinqQueryable<TDatabase>(continuationToken: pagedItem.ContinuationToken);//, linqSerializerOptions: LinqOptions);
    IQueryable<TDatabase> queryable = queryDefinition.Where(a => true);

    Expression<Func<TDatabase, bool>> predicateDb = mapper.Map<Expression<Func<TDatabase, bool>>>(predicate);
    Expression<Func<TDatabase, object>> orderByExpressionDB = mapper.Map<Expression<Func<TDatabase, object>>>(orderByExpression);

    if (predicateDb != null)
    {
        queryable = queryable.Where<TDatabase>(predicateDb);
    }

    IOrderedQueryable<TDatabase> OrderBy = null;
    if (orderByExpression != null)
    {
        if (disc)
            OrderBy = queryable.OrderByDescending(orderByExpressionDB);
        else
            OrderBy = queryable.OrderBy(orderByExpressionDB);
        queryable = OrderBy;
    }
    if (orderThenByExpressionPaged != null)
    {
        Expression<Func<TDatabase, object>> orderByExpressionThenByDB = mapper.Map<Expression<Func<TDatabase, object>>>(orderThenByExpressionPaged);
        if (pagedDesc)
            OrderBy = OrderBy.ThenByDescending(orderByExpressionThenByDB);
        else
            OrderBy = OrderBy.ThenBy(orderByExpressionThenByDB);
        queryable = OrderBy;
    }
    return queryable;
}

我尝试删除调试器中的 ContinuationToken,查询运行良好,但返回之前的结果。

c# azure linq azure-cosmosdb
1个回答
-1
投票

GetItemLinqQueryable()
方法用于创建 LINQ 查询,该查询允许从容器中检索数据。
orderByExpression
orderThenByExpressionPaged
用于对查询进行排序。

orderByExpression
使用
Expression<Func<TDatabase, object>>
定义,用于按 Age 属性对结果进行排序,PagingItem 对象用于处理分页。在此 ContinuationToken 属性用于存储并从查询的一次迭代传递到查询的下一次迭代。

在您的代码中,您没有使用

allowSynchronousQueryExecution:true
,它允许同步执行查询,不使用它会给出不同的错误。您收到的错误似乎是语法错误,您可以重用我的代码来实现所需的输出。

我只是使用 order by 过滤来展示 ORDER BY 子句在下面的代码中如何工作。

下面是我尝试过的代码

private async Task<IQueryable<TDatabase>> _GetQuery(
    Expression<Func<TDatabase, object>> orderByExpression,
    bool desc,
    PagingItem pagedItem = null,
    Expression<Func<TDatabase, object>> orderThenByExpressionPaged = null,
    bool pagedDesc = false)
{
    await Task.CompletedTask;

    var queryDefinition = container.GetItemLinqQueryable<TDatabase>(continuationToken: pagedItem?.ContinuationToken,
        allowSynchronousQueryExecution: true
        );

    IOrderedQueryable<TDatabase> queryable;

    if (desc)
        queryable = queryDefinition.OrderByDescending(orderByExpression);
    else
        queryable = queryDefinition.OrderBy(orderByExpression);

    if (orderThenByExpressionPaged != null)
    {
        if (pagedDesc)
            queryable = queryable.ThenByDescending(orderThenByExpressionPaged);
        else
            queryable = queryable.ThenBy(orderThenByExpressionPaged);
    }

    return queryable;
}

public async Task MainMethod()
{
    string orderByPropertyName = "Age"; 
    Expression<Func<TDatabase, object>> orderByExpression = CreateOrderByExpression(orderByPropertyName);

    var queryable = await _GetQuery(orderByExpression, true, null);

    var results = queryable.ToList();

    foreach (var item in results)
    {
        Console.WriteLine($"Id: {item.GetType().GetProperty("Id")?.GetValue(item)}, Name: {item.GetType().GetProperty("Name")?.GetValue(item)}, Age: {item.GetType().GetProperty("Age")?.GetValue(item)}, Field: {item.GetType().GetProperty("Field")?.GetValue(item)}");
    }
}

输出:

Id: 2, Name: Balaji, Age: 25, Field: NON-IT
Id: 1, Name: Pavan, Age: 24, Field: IT
Id: 3, Name: Pavan Balaji, Age: 23, Field: Software
© www.soinside.com 2019 - 2024. All rights reserved.