2012-03-14 2 views
1

настоящее время у меня этот Linq запрос:Как Linq-ify этот запрос?

return this.Context.StockTakeFacts 
       .OrderByDescending(stf => stf.StockTakeId) 
       .Where(stf => stf.FactKindId == ((int)kind)) 
       .Take(topCount) 
       .ToList<IStockTakeFact>(); 

Цель состоит в том, чтобы вернуться каждый факт для TopCount из StockTakes, но вместо этого я могу видеть, что я буду получать только TopCount количество фактов.

Как сделать Linq-ify этот запрос для достижения моей цели?

Я мог бы использовать 2 запроса, чтобы получить top-topCount StockTakeId, а затем сделать «между», но я подумал, какие уловки Linq могут иметь.

Это то, что я пытаюсь победить. Обратите внимание, что это действительно больше связано с тем, что вы не можете найти решение. Также беспокоился о производительности не для этих запросов, но в целом, я не хочу просто легко разбираться и узнавать, что он замирает за кулисами. Как то, каково наказание, которое содержит предложение в моем втором запросе ниже?

List<long> stids = this.Context.StockTakes 
       .OrderByDescending(st => st.StockTakeId) 
       .Take(topCount) 
       .Select(st => st.StockTakeId) 
       .ToList<long>(); 

      return this.Context.StockTakeFacts 
       .Where(stf => (stf.FactKindId == ((int)kind)) && (stids.Contains(stf.StockTakeId))) 
       .ToList<IStockTakeFact>(); 
+3

Что вы подразумеваете под Linqify? Это уже linq – manojlds

+0

@manojlds. Я предполагаю, что «Linqify» _ делает работу linq, хотя я не проверял словарь ... =) – gdoron

+0

, почему вы не выбрали факт и не примените Take (topCount) к StockTake. Вам нужно будет присоединиться к таблицам в поле «Идентификатор». – Doomsknight

ответ

0

Как насчет этого?

return this.Context.StockTakeFacts 
       .OrderByDescending(stf => stf.StockTakeId) 
       .Where(stf => stf.FactKindId == ((int)kind)) 
       .Take(topCount) 
       .Select(stf=>stf.Fact) 
       .ToList(); 
+0

Привет.нет, к сожалению, опять же он не захватывает все факторы, влияющие на верхние запасы. Он захватывает верхние фондовые индексы. – rism

0

Если я понял, что вы после этого правильно, как насчет:

return this.Context.StockTakes 
    .OrderByDescending(st => st.StockTakeId) 
    .Take(topCount) 
    .Join(
     this.Context.StockTakeFacts, 
     st => st.StockTakeId, 
     stf => stf.StockTakeId, 
     (st, stf) => stf) 
    .OrderByDescending(stf => stf.StockTakeId) 
    .ToList<IStockTakeFact>(); 
0

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

var stids = 
    from st in this.Context.StockTakes 
    orderby st.StockTakeId descending 
    select st.StockTakeId; 

var topFacts = 
    from stid in stids.Take(topCount) 
    join stf in this.Context.StockTakeFacts 
    on stid equals stf.StockTakeId 
    where stf.FactKindId == (int)kind 
    select stf; 

return topFacts.ToList<IStockTakeFact>(); 

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

Следует отметить, что во втором запросе я вызываю Take, чтобы ограничить стили topCount, используемые во втором запросе. Вместо того, чтобы иметь два запроса, я мог бы использовать into (т. Е. Продолжение запроса) в строке выбора запроса stids для объединения двух запросов, но это создало беспорядок для ограничения его на topCount элементов. Другим вариантом было бы поставить запрос stids в круглые скобки и вызывать на нем Take. Вместо этого разделение его на два вопроса показалось мне самым чистым.

Обычно я избегаю указания общих типов, когда я думаю, что компилятор может вывести тип; однако IStockTakeFact почти наверняка является интерфейсом, и любой конкретный тип реализует его, вероятно, содержится в this.Context.StockTakeFacts;, что создает необходимость указывать общий тип в вызове ToList. Обычно я опускаю параметр типового типа на мои вызовы ToList - это, кажется, элемент моих личных вкусов, ваш может отличаться. Если this.Context.StockTakeFacts уже есть List<IStockTakeFact>, вы можете спокойно опустить общий тип на вызов ToList.

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