Как провести рефакторинг нескольких похожих запросов Linq?

2

Предположим, что у меня есть два следующих запроса 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. Есть какой-либо способ поставить запрос внутри метода и передать параметр Where в качестве аргумента?

Теги:
linq
refactoring
linq-to-sql

4 ответа

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
    Почему вы указываете аргумент типа в правой части? Его вывод из lhs делает код более коротким и читаемым.
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
    Вроде не по теме, но разве этот метод не может быть приватным, статическим или и тем, и другим?
  • 1
    Это зависит - это может быть открытый метод вспомогательного класса или закрытый метод класса, который его использует. Это может быть статичным, но можно также решить оставить его нестатичным для лучшей тестируемости. Я бы не стал угадывать лучший способ, основанный на этих нескольких строках кода.
Показать ещё 1 комментарий
1

Да, тип параметра - это выражение lamba 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
    Вы действительно пробовали это?
Показать ещё 4 комментария
1

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

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

где T и U - любые типы, имеющие отношение к вашему запросу.

  • 0
    Я не привык к лямбда-выражениям, поэтому я не понял, что это так очевидно.
  • 0
    Лямбда-выражение - это не что иное, как синтаксический сахар для делегата Func <> с вставленными соответствующими универсальными типами. Там нет магии. :)
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню