2016-02-18 2 views
1

В настоящее время я использую 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 может работать на него в памяти. Это меньше, чем идеально, потому что мне нужно дополнительно уточнить запрос позже, поэтому гораздо больше данных переносится по сравнению с тем, чтобы делать все в базе данных.

ответ

2

Почему бы не выделить один запрос и запросить результаты?

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 все еще имеет некоторые морщины вокруг адаптера, так как я следил за некоторыми подобными ошибками в ветке npgsql в github.

+0

Благодарим за это, хотя он, к сожалению, производит тот же SQL-запрос. Я предполагаю, что это действительно ошибка в npgsql и будет содержать отчет об ошибке. – Ryan

Смежные вопросы