В настоящее время я использую Linq to SQL в ASP.NET Core 1.0 с адаптером npgsql PostgreSQL.LINQ to SQL [npgsql] Создание неверного запроса из SelectMany
У меня есть следующий 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, который действует как многие ко многим присоединиться к таблице между UserGroup
и DeviceGroup
.
Это затем генерирует запрос 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: колонка ugml.UserGroupId не существует
которая, как представляется, так как SQL-запрос почему-то делает SELECT FROM "Device" AS ugml
вместо SELECT FROM "UserGroupMembershipList" AS ugml
. Кроме того, предложение where выглядит неверно из-за этого.
Я делаю что-то не так, когда дело доходит до запроса Linq? Есть ли какие-то другие способы сделать то, что я пытаюсь сделать, чтобы избежать этой ошибки?
EDIT:
Я нашел работу вокруг, хотя это меньше, чем идеал.
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 может работать на него в памяти. Это меньше, чем идеально, потому что мне нужно дополнительно уточнить запрос позже, поэтому гораздо больше данных переносится по сравнению с тем, чтобы делать все в базе данных.
Благодарим за это, хотя он, к сожалению, производит тот же SQL-запрос. Я предполагаю, что это действительно ошибка в npgsql и будет содержать отчет об ошибке. – Ryan