2012-03-14 2 views
5

В настоящее время я пытаюсь понять некоторые основы с LINQ. Я использую LINQPad для запроса источника OData Netflix.LINQ Lambda query 'select' не работает с oData

Источник:http://odata.netflix.com/v2/Catalog/

Я не могу показаться, чтобы выбрать отдельные свойства при использовании лямбда-запроса - запрос понимания работает отлично. Я нашел фрагмент кода, который выполняет более сложный запрос с использованием lambdas в источнике Oflata Netflix, и это, похоже, отлично работает для возврата одного свойства объекта.

// works fine 
var compQuery = from t in Titles 
       where t.ReleaseYear == 2007 
       select new { t.Name }; 
compQuery.Dump(); 



// fails: "Can only specify query options (orderby, where, take, skip) after last navigation." 
var lambdaQuery = Titles 
      .Where(t => t.ReleaseYear == 2007) 
      .Select(t => t.Name); 

lambdaQuery.Dump(); 


// works fine - found on SO. 
var lambdaQuery2 = People 
    .Expand("TitlesActedIn") 
    .Where(p => p.Name == "George Lucas") 
    .First() 
    .TitlesActedIn.Select(t => t.ShortName);    

lambdaQuery2.Dump(); 

Может кто-нибудь пролить некоторый свет на то, почему основной лямбда-запроса неудовлетворительную, когда их просят вернуть одно свойство?

ответ

4

Попробуйте этом- это то, что фактически эквивалентно вашей первой один:

// fails: "Can only specify query options (orderby, where, take, skip) after last navigation." 
var lambdaQuery = Titles 
      .Where(t => t.ReleaseYear == 2007) 
      .Select(t => new { t.Name }); 

lambdaQuery.Dump(); 
+0

ahhh, я пробовал это сейчас, и он работает! - Я не понимаю, как другой лямбда-запрос (люди) не требует от меня создания анонимного типа для проецирования? – Dal

+0

Поскольку вы вызываете '.First()' на нем, что материализует результаты, оно отсасывает всю запись и затем выбирает свойства в памяти на клиенте. –

+0

Не могли бы вы объяснить, почему для этого требуется использование анонимного типа? Спасибо –

12

OData не имеет поддержки для проецирования на свойства - вы можете обойти эту проблему, хотя:

var lambdaQuery = Titles 
      .Where(t => t.ReleaseYear == 2007) 
      .Select(x=> new { x.Name }) 
      .AsEnumerable() 
      .Select(t => t.Name); 

Использование AsEnumerable() заставляет последнюю часть запроса выполнять в контексте Linq-to-Objects (вместо запроса OData), где проекция работает просто отлично.

+0

Спасибо, что работает. Я нашел здесь дополнительную информацию относительно AsEnumerable - http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataservices/thread/d427cbf6-4d8a-42ee-9799-d5ca79e581dc – Dal

+0

Хотелось бы, чтобы я мог проверить это с работы (Netflix заблокирован здесь), но является ли первая проекция действительно необходимой? Кажется, здесь немного избыточно. –

+0

@JeffMercado: Согласно Odata (и ссылка в комментариях выше) проекция одаты отправит сам объект, но не содержит свойств, которые не нужны - поэтому лучше всего, чтобы производительность оставила это, чтобы уменьшить количество данные, которые проходят через провод – BrokenGlass

0

Используя ответы, данные, я провел несколько тестов и обнаружил некоторые интересные вещи, касающиеся времени выполнения:

// Avg Execution Time: 5 seconds 
var query1 = Titles 
      .Where(t => t.ReleaseYear == 2007) 
      .Select(t => new {t.Name});  
query1.Dump(); 


// Avg Execution Time: 15 seconds 
var query2 = Titles 
      .Where(t => t.ReleaseYear == 2007) 
      .AsEnumerable() 
      .Select(t => t.Name);  
query2.Dump(); 

Так я прав, полагая, что в запросе 1, свойство «Name» возвращается только ? Если в запросе 2 метод «AsEnumerable()» возвращает объект со всеми значениями свойств и, следовательно, более длительным временем выполнения?

+0

Да, переданные данные намного больше для query2 И поскольку вы запрашиваете целые объекты, они получают отслеживание изменений по контексту. – springy76