У меня проблемы с построением запроса Entity Framework LINQ, предложение которого содержит вызовы методов для объектов, не являющихся EF.
Приведенный ниже код является частью приложения, используемого для преобразования данных из одной СУБД в другую схему в другой СУБД. В приведенном ниже коде Role - это мой пользовательский класс, не связанный с СУБД, а все остальные классы созданы Entity Framework из моей схемы БД:
// set up ObjectContext's for Old and new DB schemas
var New = new NewModel.NewEntities();
var Old = new OldModel.OldEntities();
// cache all Role names and IDs in the new-schema roles table into a dictionary
var newRoles = New.roles.ToDictionary(row => row.rolename, row => row.roleid);
// create a list or Role objects where Name is name in the old DB, while
// ID is the ID corresponding to that name in the new DB
var roles = from rl in Old.userrolelinks
join r in Old.roles on rl.RoleID equals r.RoleID
where rl.UserID == userId
select new Role { Name = r.RoleName, ID = newRoles[r.RoleName] };
var list = roles.ToList();
Но вызов ToList дает мне это исключение NotSupportedException:
LINQ to Entities не распознает
метод Int32
get_Item (System.String) 'и
этот метод не может быть переведен на
магазинное выражение
Звучит так, как будто LINQ-to-Entities препятствует моему вызову, чтобы вытащить значение из словаря с указанным именем в качестве ключа. Я, правда, недостаточно разбираюсь в EF, чтобы понять, почему это проблема.
Я использую devart dotConnect для PostgreSQL провайдера инфраструктуры сущностей, хотя на этом этапе я предполагаю, что это не специфичная для СУБД проблема.
Я знаю, что могу заставить его работать, разделив мой запрос на два запроса, например:
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 roles2 = from r in roles.AsEnumerable()
select new Role { Name = r.RoleName, ID = newRoles[r.RoleName] };
var list = roles2.ToList();
Но мне было интересно, есть ли более элегантный и / или более эффективный способ решить эту проблему, в идеале, не разбивая ее на два запроса.
Во всяком случае, мой вопрос состоит из двух частей:
Во-первых, могу ли я преобразовать этот запрос LINQ во что-то, что Entity Framework примет, в идеале, без разделения на две части?
Во-вторых, я также хотел бы немного разобраться в EF, чтобы понять, почему EF не может наложить свой собственный код .NET поверх доступа к БД. Моя СУБД понятия не имеет, как вызвать метод в классе Dictionary, но почему EF просто не может выполнить эти вызовы метода Dictionary после того, как данные уже получены из БД? Конечно, если бы я хотел составить несколько запросов EF вместе и поместить собственный код .NET в середину, я бы ожидал, что это не удастся, но в этом случае код .NET только в конце, так почему это проблема для EF? Я предполагаю, что ответ что-то вроде «эта функция не вошла в EF 1.0», но я ищу немного больше объяснения о том, почему это достаточно сложно оправдать, чтобы исключить его из EF 1.0.