#c# #.net #entity-framework
#c# #.net #entity-framework
Вопрос:
Я фильтрую данные, используя обнуляемую переменную.
Если переменная равна null, фильтр отключен.
Есть ли более приятный способ написать:
GetQuery().Where(pd=> (!customerId.HasValue || pd.CustomerId==customerId.Value))
(У меня более 4 фильтров, и это выглядит как огромный блок беспорядка)
Ответ №1:
Ваш пример:
GetQuery().Where(pd=> (!customerId.HasValue || pd.CustomerId==customerId.Value))
может быть написано с использованием оператора объединения null ??
:
GetQuery().Where( pd => pd.CustomerID == ( customerId ?? pd.CustomerID ) )
Не уверен, что это что-то улучшает, но это вариант.
Комментарии:
1. Это интересно, хотя вы, я полагаю, имеете в виду, что вы
customerId ?? pd.CustomerID
заключены в скобки, иначе это было бы недопустимым выражением (в общем случае).2. Интересно. Я бы подумал,
??
что привязка будет более жесткой, чем==
Ответ №2:
Возможно, вы могли бы использовать метод расширения для его создания.
public static IQueryable<T> OptionalWhere<T>(this IQueryable<T> query, int? id, Expression<Func<T, int, bool>> filter)
{
if (id.HasValue)
{
var idValue = id.Value;
query = query.Where(e => filter(e, idValue));
}
return query;
}
Затем запрос в становится:
var q = GetQuery().OptionalWhere(customerId, (pd, id) => pd.CustomerId == id);
Комментарии:
1. Есть ли способ написать этот метод для каждого обнуляемого типа (long?, int?, string и так далее)?
2. @Naor Типы с нулевым значением (которые не включают
string
) являются экземплярамиNullable<T>
. Вы всегда можете задать типid
параметраNullable<T>
(хотя, опять же, это не поможет вам работать со строками).3. Вы не можете волшебным образом вызвать подобное выражение … вам пришлось бы его перестроить.
Ответ №3:
Нет, лучшего способа написать то же самое не существует. Однако я должен сказать, что для нужной вам логики (что не является стандартным значением null
в обнуляемом типе) оно довольно короткое. Я не думаю, что вы можете ожидать, что оно станет короче.
Я не нахожу его особенно нечитаемым или беспорядочным, даже если у вас было 4 или даже 10 копий этой строки друг под другом. Самое короткое, о чем я могу подумать, это:
GetQuery().Where(pd => customerId == null || pd.CustomerId == customerId)
.Where(pd => customerName == null || pd.CustomerName == customerName)
.Where(pd => customerAddress == null || pd.CustomerAddress == customerAddress)
.Where(pd => customerPostcode == null || pd.CustomerPostcode == customerPostcode)
.Where(pd => customerCountry == null || pd.CustomerCountry == customerCountry)
.Where(pd => customerPhoneNumber == null || pd.CustomerPhoneNumber == customerPhoneNumber)
Комментарии:
1. Я на самом деле использовал . Где(pd=> … amp;amp; … amp;amp; …) а не Where для каждого условия. Влияет ли это на эффективность?
2. @Naor: Это не имеет заметного значения. Если это LINQ-to-SQL, то это даже вообще не имеет никакого значения.
3. Я не могу говорить об эффективности, но я бы определенно связал методы расширения LINQ в цепочку, прежде чем объединять большое количество условий в одном анонимном предикате…