Кажется, что существует 4 достойных реализации JAX-RS, таким образом, Вы соглашаетесь, вероятно, с любым из них. Если это имеет значение я нашел Джерси (1.0.2) действительно хорошим до сих пор. Мои потребности являются довольно скромной, простой серверной службой, заботятся об инфраструктуре и так далее. И что Джерси делает вполне приятно.
Проблема в том, что при использовании отложенного выполнения Linq вам действительно нужно решить, где вы хотите обрабатывать и какие данные вы хотите передавать по каналу в ваше клиентское приложение. В первом случае Linq разрешает выражение и извлекает все данные роли в качестве предшественника
New.roles.ToDictionary(row => row.rolename, row => row.roleid);
. В этот момент данные перемещаются из базы данных в клиент и преобразуются в ваш словарь. Пока все хорошо.
Проблема в том, что ваше второе выражение Linq просит Linq выполнить преобразование во второй БД , используя для этого словарь в БД . Другими словами, он пытается найти способ передать всю структуру словаря в БД, чтобы он мог выбрать правильное значение идентификатора как часть отложенного выполнения запроса. Я подозреваю, что он отлично разрешится, если вы измените вторую половину на
var roles = from rl in Old.userrolelinks
join r in Old.roles on rl.RoleID equals r.RoleID
where rl.UserID == userId
select r.RoleName;
var list = roles.ToDictionary(roleName => roleName, newRoles[roleName]);
. Таким образом, он разрешит ваш выбор в БД (выбрав только имя роли) в качестве предшественника обработки вызова ToDictionary (что он должен делать на клиенте. как и следовало ожидать). По сути, это именно то, что вы делаете во втором примере, потому что AsEnumerable передает данные клиенту перед их использованием в вызове ToList. Вы можете легко изменить его на что-нибудь вроде
var roles = from rl in Old.userrolelinks
join r in Old.roles on rl.RoleID equals r.RoleID
where rl.UserID == userId
select r;
var list = roles.AsEnumerable().Select(r => new Role { Name = r.RoleName, ID = newRoles[r.RoleName] });
, и все будет так же. Вызов AsEnumerable () разрешает запрос, передавая данные клиенту для использования в следующем за ним Select.
Обратите внимание, что я не тестировал это, но насколько я понимаю Entity Framework, это мое лучшее объяснение о том, что происходит под капотом.
он разрешает ваш выбор в БД (выбирая только имя роли) в качестве предшественника обработки вызова ToDictionary (что он должен делать на клиенте, как и следовало ожидать). По сути, это именно то, что вы делаете во втором примере, потому что AsEnumerable извлекает данные клиенту, прежде чем использовать их в вызове ToList. Вы можете легко изменить его на что-то вродеvar roles = from rl in Old.userrolelinks
join r in Old.roles on rl.RoleID equals r.RoleID
where rl.UserID == userId
select r;
var list = roles.AsEnumerable().Select(r => new Role { Name = r.RoleName, ID = newRoles[r.RoleName] });
, и все будет так же. Вызов AsEnumerable () разрешает запрос, передавая данные клиенту для использования в следующем за ним Select.
Обратите внимание, что я не тестировал это, но насколько я понимаю Entity Framework, это мое лучшее объяснение о том, что происходит под капотом.
он разрешает ваш выбор в БД (выбирая только имя роли) в качестве предшественника обработки вызова ToDictionary (что он должен делать на клиенте, как и следовало ожидать). По сути, это именно то, что вы делаете во втором примере, потому что AsEnumerable извлекает данные клиенту, прежде чем использовать их в вызове ToList. Вы можете легко изменить его на что-нибудь вродеvar roles = from rl in Old.userrolelinks
join r in Old.roles on rl.RoleID equals r.RoleID
where rl.UserID == userId
select r;
var list = roles.AsEnumerable().Select(r => new Role { Name = r.RoleName, ID = newRoles[r.RoleName] });
, и все будет так же. Вызов AsEnumerable () разрешает запрос, передавая данные клиенту для использования в следующем за ним Select.
Обратите внимание, что я не тестировал это, но насколько я понимаю Entity Framework, это мое лучшее объяснение о том, что происходит под капотом.
По сути, это именно то, что вы делаете во втором примере, потому что AsEnumerable передает данные клиенту перед их использованием в вызове ToList. Вы можете легко изменить его на что-то вродеvar roles = from rl in Old.userrolelinks
join r in Old.roles on rl.RoleID equals r.RoleID
where rl.UserID == userId
select r;
var list = roles.AsEnumerable().Select(r => new Role { Name = r.RoleName, ID = newRoles[r.RoleName] });
, и все будет так же. Вызов AsEnumerable () разрешает запрос, передавая данные клиенту для использования в следующем за ним Select.
Обратите внимание, что я не тестировал это, но насколько я понимаю Entity Framework, это мое лучшее объяснение о том, что происходит под капотом.
По сути, это именно то, что вы делаете во втором примере, потому что AsEnumerable передает данные клиенту перед их использованием в вызове ToList. Вы можете легко изменить его на что-нибудь вродеvar roles = from rl in Old.userrolelinks
join r in Old.roles on rl.RoleID equals r.RoleID
where rl.UserID == userId
select r;
var list = roles.AsEnumerable().Select(r => new Role { Name = r.RoleName, ID = newRoles[r.RoleName] });
, и все будет так же. Вызов AsEnumerable () разрешает запрос, передавая данные клиенту для использования в следующем за ним Select.
Обратите внимание, что я не тестировал это, но насколько я понимаю Entity Framework, это мое лучшее объяснение о том, что происходит под капотом.
Джейкоб совершенно прав.
Вы не можете преобразовать желаемый запрос, не разделив его на две части, поскольку Entity Framework не может преобразовать вызов get_Item в запрос SQL.
Единственный способ - написать запрос LINQ to Entities, а затем написать запрос LINQ to Objects к его результату, как советовал Джейкоб.
Проблема специфична для Entity-Framework, она не возникает из-за нашей реализации поддержки Entity Framework.