2012-05-30 3 views
1

У меня есть строка кода LINQ, которая генерирует исключение System.NotSupportedException.Почему LINQ-версия этого цикла foreach генерирует исключение NotSupportedException («NotSupportedException»)?

 return unconvertedUrls 
        .Select(potentialQueryURL => ConvertPotentialQueryURLToSeed(potentialQueryURL)) 
        .Where(id => id > 0) 
        .ToList(); 

Сообщение исключение «Метод„Int32 ConvertPotentialQueryURLToSeed (SeedsSQLConnector.PotentialQueryURL)“не поддерживается перевод на SQL»

Однако простое преобразование в цикле Еогеасп работает без проблем.

 var result = new List<int>(); 
     foreach (var potentialQueryURL in unconvertedUrls) 
     { 
      var id = ConvertPotentialQueryURLToSeed(potentialQueryURL); 
      if (id > 0) 
      { 
       result.Add(id); 
      } 
     } 
     return result; 

Что происходит не так и почему?

========== ========== EDIT

Одд, коллега предложил другое исправление, которое тоже работает. Похоже, LINQ передавал в базу данных ConvertPotentialQueryURLToSeed! Во всяком случае, вот другой фикс, который должен добавить .ToList() к предыдущему заявлению:

 var unconvertedUrls = (from url in _DataContext.PotentialQueryURLs 
           where !convertedUrlIds.Contains(url.Id) 
           select url).ToList(); 
     return unconvertedUrls 
        .Select(potentialQueryURL => ConvertPotentialQueryURLToSeed(potentialQueryURL)) 
        .Where(id => id > 0) 
        .ToList(); 
+0

Я подозреваю, что вы используете EF или NHibernate, проблема в том, что ORM не может перевести то, что вы ввели в SQL. Что делает ваша функция? Можете ли вы показать нам это? Второй пример работает, потому что вы не запрашиваете базу данных. – mattytommo

ответ

3

Причина заключается в том, что LINQ к SQL не выполняет этот код запроса, но пытается преобразовать его в SQL заявление. Поскольку он не знает ConvertPotentialQueryURLToSeed, это преобразование не удается.

Работа foreach работает, потому что в этом случае метод ConvertPotentialQueryURLToSeed не используется в той части запроса LINQ, которая переводится на SQL.

Версия с ToList работает по той же причине: ToList извлекает данные из запроса до сих пор из базы данных. С этого момента вы работаете над обычными объектами C#, а также LINQ to Objects.

+0

Спасибо, Дэниэл, я помету это как ответ через шесть минут. Есть ли способ сообщить LINQ, что функция является локальной, а не базовой? Добавление ToList() в предыдущее заявление, похоже, делает это (см. Редактирование вопроса), но есть ли более читаемый способ? – dumbledad

+0

@dumbledad. Ваше редактирование работает, потому что вы разрешили список с помощью 'ToList' и эффективно выполнили LINQ для коллекции in-memory во втором операторе, поэтому второй оператор не вызывает базу данных. – mattytommo

+1

@ dumbledad: Нет, другого пути нет. –

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