2009-05-14 3 views
2

Предположим, у меня есть два следующих Linq запросов, которые я хочу, чтобы реорганизовать:Как реорганизовать несколько похожих запросов Linq?

var someValue1 = 0; 
var someValue2= 0; 
var query1 = db.TableAs.Where(a => a.TableBs.Count() > someValue1) 
        .Take(10); 
var query2 = db.TableAs.Where(a => a.TableBs.First().item1 == someValue2) 
        .Take(10); 

Обратите внимание, что только в случае изменения параметров. Есть какой-либо способ поставить запрос внутри метода и передать параметр Where в качестве аргумента?

ответ

2

Кауса есть. Параметр where - это просто закрытие типа Func<T, bool> (где T - тип ваших элементов БД - я не знаю их из вашего кода), и вы можете обернуть его в (анонимную) функцию.

Func<Func<T, bool>, IEnumerable<T>> MakeQuery = (Func<T, bool> whereParam) => db.TableAs.Where(whereParam).Take(10); 

Используйте его как этот

var query1 = MakeQuery(a => a.TableBS.Count() > someValue1); 
+0

Почему вы указываете тип аргумент о rhs? Его вывод из lhs делает код более коротким и читаемым. – nawfal

1

Да, тип параметра является выражением Ламбы Func<TSource, bool>

Func<Person, bool> c1 = p => p.LastName == "1"; 
Persons.Where(c1); 
Func<Person, bool> c2 = p => p.FirstName == "2"; 
Persons.Where(c2) 
+0

Это не работает: неподдерживаемая перегрузка используется для оператора запроса «Где». –

+0

Вы на самом деле пробовали это? –

+0

Да, я собрал и побежал перед публикацией здесь. –

1

Вы можете сделать это так же, как вы бы рефакторинг любой другой код:

T MyQuery(U db, Func<TSource, bool> pred) { 
    return db.TableAs.Where(pred) 
        .Take(10); 
} 

где T и U являются любые типы Är erelevant в Ваш запрос.

+0

Я не привык к лямбда-выражениям, поэтому я не понял, что это так очевидно. –

+0

Выражение лямбда - это не что иное, как синтаксический сахар для делегата Func <> с соответствующими вставленными родовыми типами. Нет волшебства. :) – jalf

+0

Это решение не работает: неподдерживаемая перегрузка используется для оператора запроса «Где». –

2

Вы можете использовать Predicate<T>.

public IQueryable<TableA> Helper(Predicate<TableA> predicate) 
{ 
    return db.TableAs.Where(predicate).Take(10); 
} 

Просто позвоните так.

var query1 = Helper(a => a.TableBs.Count() > someValue1); 
var query2 = Helper(a => a.TableBs.First().item1 == someValue2); 

И дать лучше, чем Helper.

+1

Вид не по теме, но не должен ли этот метод быть либо приватным, либо статическим или обоими? – Svish

+1

Это зависит от этого - это может быть общедоступный метод вспомогательного класса или частный метод класса, который его использует. Он может быть статичным, но можно также решить, что он нестатический для лучшей проверки. Я бы не попытался угадать лучший способ, основанный на этих нескольких строках кода. –

+0

Просто коррекция, Где принимает Func , а не предикат , но у меня появилась идея. –

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