【问题标题】:Problem using LINQ queries with GetItemLinqQueryable for CosmosDB对 CosmosDB 使用带有 GetItemLinqQueryable 的 LINQ 查询时出现问题
【发布时间】:2021-01-17 05:06:07
【问题描述】:

我在对 CosmosDB 容器使用 linq 查询时遇到了挑战,想知道是否有人有一些提示。

容器名为Departments,有多个“Departments”条目,每个部门都有一个嵌套数组“Employees”和employee-“objects”,如果没有employee则可以为空。

{
    "Name": "Microsoft",
    "Employees": [
        {
            "Firstname": "Lars",
            "Lastname": "Larsen",
            "Startdate": "2017-01-01T00:00:00",
            "Enddate": "0001-01-01T00:00:00",
            "Birthdate": "1983-01-10T00:00:00",
            "DepartmentID": "b70ab2b6-58d7-45bb-9b13-49f7d97a8aea",
            "Department": null,
            "PositionID": "1ba094a4-ce2e-463c-b45e-a81231070ed8",
            "Position": null,
            "id": "68991651-400c-427b-8839-3f1bcfc72054"
        },
        {
            "Firstname": "Knut",
            "Lastname": "Knutsen",
            "Startdate": "2019-06-15T00:00:00",
            "Enddate": "0001-01-01T00:00:00",
            "Birthdate": "1992-01-10T00:00:00",
            "DepartmentID": "b70ab2b6-58d7-45bb-9b13-49f7d97a8aea",
            "Department": null,
            "PositionID": "3ba04314-02ff-4603-b80e-b71e316e9c37",
            "Position": null,
            "id": "e106fbc7-c791-446e-a163-a5d29512980e"
        }
    ],
    "id": "b70ab2b6-58d7-45bb-9b13-49f7d97a8aea",
    "_rid": "qwN-AML8frwCAAAAAAAAAA==",
    "_self": "dbs/qwN-AA==/colls/qwN-AML8frw=/docs/qwN-AML8frwCAAAAAAAAAA==/",
    "_etag": "\"00000000-0000-0000-9594-5efd0a9f01d6\"",
    "_attachments": "attachments/",
    "_ts": 1601296753

我的目标是只返回员工列表,而不考虑部门。 在带有查询字符串“SELECT * FROM ch in c.Employees”的后端 C# 代码中,它可以完美运行。

这是带有正在运行的 SQL 字符串的代码:

var query = "SELECT * FROM ch in c.Employees";

        var queryDefinition =
            new QueryDefinition(
                query);

        var setIterator =
            _container.GetItemQueryIterator<Employee>(
                queryDefinition);

        var entityList = new List<Employee>();

        while (setIterator.HasMoreResults)
        {
            entityList.AddRange(await setIterator.ReadNextAsync());
        };

        return entityList;

以下代码重写适用于 LINQ 查询,但我在检索所有员工之后执行它,当我稍后添加过滤以按部门、职位等获取特定员工时,这是不必要的。这是工作示例:

using (FeedIterator<Department> setIterator = _container.GetItemLinqQueryable<Department>().ToFeedIterator())
        {
            var entityList = new List<Department>();

            while (setIterator.HasMoreResults)
            {
                entityList.AddRange(await setIterator.ReadNextAsync());
            };

            var employeeList = entityList.SelectMany(c => c.Employees).ToList();

            return employeeList;
        }

但是,如果我将 linq 查询作为 GetItemLinqQueryable 的一部分移动,则会收到错误消息“IQueryable 不包含 'ToFeedIterator' 的定义,并且还会出现错误,因为它无法从部门转换为员工。

这在 .SelectMany(c => c.Employees) 和 await setIterator.ReadNextAsync() 上有错误,但不知道如何可视化它。但这是代码。

using (FeedIterator<Department> setIterator = _container.GetItemLinqQueryable<Department>()
            .SelectMany(c => c.Employees)
            .ToFeedIterator<Department>())
        {
            var entityList = new List<Employee>();

            while (setIterator.HasMoreResults)
            {
                entityList.AddRange(await setIterator.ReadNextAsync());
            };

            return entityList;
        }

是否有人知道是否有可能完成所有这些操作并在附加到 cosmosDB 的一个查询中在 linq 中进行过滤,因此我不需要让所有员工离开然后进行过滤?

谢谢! 希望我的帖子不会太混乱,我尽量说清楚。

【问题讨论】:

    标签: c# sql linq asp.net-core azure-cosmosdb


    【解决方案1】:

    请试试这个:

    using (FeedIterator<Employee> setIterator = container.GetItemLinqQueryable<Department>()
                    .SelectMany(c => c.Employees)
                    .ToFeedIterator<Employee>())
                {
                    var entityList = new List<Employee>();
    
                    while (setIterator.HasMoreResults)
                    {
                        entityList.AddRange(await setIterator.ReadNextAsync());
                    };
    
                    return entityList;
                }
    

    结果:

    顺便说一句,下面的代码也可以正常工作。

    var entityList = container.GetItemLinqQueryable<Department>(true).SelectMany(c => c.Employees).ToList<Employee>();
    return entityList;
    

    【讨论】:

      【解决方案2】:

      你可以试试

       var queryOptions = new QueryRequestOptions
                  {
                      MaxConcurrency = -1,
                      PartitionKey = PartitionKey.None;// May be null
                  };
      
                   _container.GetItemLinqQueryable<Department>(requestOptions: queryOptions)
                  .SelectMany(c => c.Employees)
                  .ToFeedIterator<Department>())
      

      【讨论】:

        猜你喜欢
        • 2021-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-07
        相关资源
        最近更新 更多