LINQ to SQL [npgsql] 从 SelectMany 生成不正确的查询

本文关键字:不正确 查询 SelectMany SQL to npgsql LINQ | 更新日期: 2023-09-27 18:35:12

我目前正在使用 Linq to SQL in ASP.NET Core 1.0 和 npgsql PostgreSQL 适配器。

我有以下 LINQ 查询,它应该返回类型 Device

的列表
var devices = DeviceConfigurationDbContext.UserGroupMembershipList
            .AsNoTracking()
            .Where(ugml => ugml.UserId == currentUser.Id)
            .Select(ugml => ugml.UserGroup)
            .SelectMany(ug => ug.UserGroupAccessList)
            .Select(uga => uga.DeviceGroup)
            .SelectMany(dg => dg.Devices);

此代码的目的是通过对UserGroupMembershipList执行Where来查找允许特定用户访问的所有设备,然后将其余表连接起来,直到达到Device列表。

实体之间的关系是:

UserGroupMembershipList -(多对一)-> UserGroup -(一对多)-> UserGroupAccessList -(多对一)-> DeviceGroup -(一对多)-> Device

UserGroupAccessList 是一个 ACL,它充当 UserGroupDeviceGroup 之间的多对多连接表。

然后生成 SQL 查询:

SELECT "ugml"."Id", "ugml"."DeviceGroupId", "d"."DeviceGroupId", "d"."Name", "uga.DeviceGroup"."Id"
FROM "Device" AS "ugml"
INNER JOIN "UserGroup" AS "ugml.UserGroup" ON "ugml"."UserGroupId" = "ugml.UserGroup"."Id"
CROSS JOIN "UserGroupAccess" AS "uga"
INNER JOIN "DeviceGroup" AS "uga.DeviceGroup" ON "uga"."DeviceGroupId" = "uga.DeviceGroup"."Id"
CROSS JOIN "Device" AS "d"
WHERE ("ugml"."UserId" = @__currentUser_Id_0) AND ("ugml.UserGroup"."Id" = "ugml"."UserGroupId")

这反过来又会产生错误

迭代 查询。Npgsql.NpgsqlException: 42703: column ugml.用户组标识不 存在

这似乎是因为SQL查询出于某种原因正在执行SELECT FROM "Device" AS ugml而不是SELECT FROM "UserGroupMembershipList" AS ugml。此外,由于这个原因,where 子句似乎不正确。

Linq 查询方面,我做错了什么吗?有没有其他方法可以完成我正在尝试完成的工作,从而避免此错误?

编辑:

我找到了一个解决方法,尽管它不太理想。

var devices = (await DeviceConfigurationDbContext.UserGroupMembershipList
            .AsNoTracking()
            .Where(ugml => ugml.UserId == currentUser.Id)
            .Include(o => o.UserGroup)
                .ThenInclude(o => o.UserGroupAccessList)
                .ThenInclude(o => o.DeviceGroup)
                .ThenInclude(o => o.Devices)
                .ToListAsync())
            .Select(ugml => ugml.UserGroup)
            .SelectMany(ug => ug.UserGroupAccessList)
            .Select(uga => uga.DeviceGroup)
            .SelectMany(dg => dg.Devices);

这使得查询在WHERE之后连接表,然后返回整个结果集作为List,标准Linq可以在内存中对其进行操作。这不太理想,因为我需要在之后进一步细化查询,与在数据库中执行所有操作相比,传输的数据要多得多。

LINQ to SQL [npgsql] 从 SelectMany 生成不正确的查询

为什么不发出单个选择查询并投影结果?

var devices = await DeviceConfigurationDbContext.UserGroupMembershipList
              .AsNoTracking()
              .Where(ugml => ugml.UserId == currentUser.Id)
              .Include(o => o.UserGroup)
              .ThenInclude(o => o.UserGroupAccessList)
              .ThenInclude(o => o.DeviceGroup)
              .ThenInclude(o => o.Devices)
              .SelectMany(ugml =>  ugml.UserGroup.UserGroupAccessLists
                                       .Select(ugal => ugal.DeviceGroup.Devices)
              .ToListAsync();

尝试上述查询,如果您发现任何问题,请告诉我们。

如果您仍然看到问题,我怀疑 npgsql 适配器周围仍然存在一些皱纹,因为我在 github 的 npgsql 分支中遵循了一些类似的错误。