LINQ to SQL [npgsql]从SelectMany生成错误的查询

时间:2016-02-18 05:00:59

标签: c# linq postgresql entity-framework-core npgsql

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

我有以下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);

此代码的目的是通过对Where执行UserGroupMembershipList找到允许某个用户访问的所有设备,然后加入其余表,直到列表为已到达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")

反过来会产生错误

  

在迭代a的结果时数据库中发生异常   查询。 Npgsql.NpgsqlException:42703:列ugml.UserGroupId没有   存在

这似乎是因为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可以在内存中对其进行操作。它不太理想,因为我之后需要进一步细化查询,与数据库中的所有内容相比,传输的数据更多。

1 个答案:

答案 0 :(得分:2)

为什么不发出一个Select查询并将结果预测出来?

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分支中跟踪了一些类似的错误。