【问题标题】:Dynamic Linq nested Select on collection property集合属性上的动态 Linq 嵌套选择
【发布时间】:2021-10-11 14:31:06
【问题描述】:

我们在 dotnet core 5.0 API 中使用 GraphQL Dotnet。

我们有一个这样的关系数据结构

Organisation --> (Zero or many) Employers --> (Zero or many) Departments.

为了优化我们的数据库查询,我们正在对查询进行一些解析,并希望使用dynamic linq 限制 SQL 返回的字段。

他们有一些像这样的非常基本的例子

 var resultDynamic = context.Customers
             .Select("new { City, CompanyName }")
             .ToDynamicList();

因此您可以选择Customers.City 和Customers.CompanyName 到一个新的动态对象列表中。

这离我们想要做的并不远,但是,我们想要查询的一些属性嵌套在集合中。

例如以下 graphQL 查询

organisations {
  id,
  name,
  employers {
    addressLine1
    }
  }
}

应该返回填充了 id 和 name 的组织列表,以及只填充了 addressline1 的雇主列表。

如果我们的查询是Database.Organisations.Include(x => x.Employers);,graphql 会很好地解析它,并且我们会返回正确的信息。但是,如果您检查 SQL,它会获取组织的每个字段,以及雇主的每个字段,而 GQL 基本上是在修剪数据客户端。

使用动态 linq 我可以做到这一点

Database.Organisations.Select("new Organisation {id, name}");

而且效果很好,返回填充了 id 和 name 的组织,这些是 SQL select 语句中唯一的 SQL 字段。

但是,当我尝试选择雇主的 addressLine1 字段时,我遇到了一些障碍。

我能做到

Database.Organisatons.Select("new Organisation {id, name, employers}");

它只会从组织中选择必填字段,但会选择所有雇主字段(并且 GQL 会修剪客户端)但我无法找到一种方法来执行 employers.addressLine1 以便仅在 sql 中进行子查询选择一个字段。

尝试像Organisations.Select("new Organisation {id, name, employers.name}"); 这样的东西只会导致

No property or field 'name' exists in type 'List`1'

这显然是因为 I Employers 是一个 List 属性,而我基本上是在尝试获取该 (List).Name ... 它不存在。

理想情况下,我想以这种基于字符串的选择格式执行此操作,因为我可以通过解析 GraphQL 查询来构建它,然后我只能从子对象中选择所需的字段,但我不知道它的格式是什么将是并且找不到任何示例。

【问题讨论】:

标签: c# linq graphql dynamic-linq


【解决方案1】:

employers.Select(name) 应该可以。

LinqPad 中的示例:

void Main()
{
    Rooms.Dump();
    (Rooms.Where(r => r.Id == 3) as IQueryable).Select("new { name, RoomReservations.Select(CheckinDate) as CheckinDates }").Dump();
}

结果为:

并且生成的 SQL 看起来像(在查询中只选择了 'name' 和 'CheckinDate'):

-- Region Parameters
DECLARE @p0 Int = 3
-- EndRegion
SELECT [t0].[Name], [t1].[CheckinDate], (
    SELECT COUNT(*)
    FROM [Reservations] AS [t2]
    WHERE [t2].[RoomId] = [t0].[Id]
    ) AS [value]
FROM [Rooms] AS [t0]
LEFT OUTER JOIN [Reservations] AS [t1] ON [t1].[RoomId] = [t0].[Id]
WHERE [t0].[Id] = @p0
ORDER BY [t0].[Id], [t1].[Id]

--> 请注意,我尝试创建一个使用 DynamicLinq 的 GraphQL 库,但并非所有逻辑都受支持。你可以看看这里: https://github.com/StefH/GraphQL.EntityFrameworkCore.DynamicLinq

【讨论】:

    猜你喜欢
    • 2021-05-25
    • 2019-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多