Условные запросы Linq

Мы работаем над Log Viewer. Использование будет иметь возможность фильтровать по пользователю, серьезность и т. Д. В Sql-дни я бы добавил к строке запроса, но я хочу сделать это с Linq. Как я могу условно добавить предложения where-clauses?

если вы хотите только фильтровать, если определенные критерии пройдены, сделайте что-то вроде этого

var logs = from log in context.Logs select log; if (filterBySeverity) logs = logs.Where(p => p.Severity == severity); if (filterByUser) logs = logs.Where(p => p.User == user); 

Таким образом, ваше дерево выражений будет именно тем, что вы хотите. Таким образом, созданный SQL будет именно тем, что вам нужно, и не что иное.

Если вам необходимо отфильтровать базу в списке / массиве, используйте следующую команду:

  public List GetData(List Numbers, List Letters) { if (Numbers == null) Numbers = new List(); if (Letters == null) Letters = new List(); var q = from d in database.table where (Numbers.Count == 0 || Numbers.Contains(d.Number)) where (Letters.Count == 0 || Letters.Contains(d.Letter)) select new Data { Number = d.Number, Letter = d.Letter, }; return q.ToList(); } 

Я закончил использовать ответ, похожий на Daren’s, но с интерфейсом IQueryable:

 IQueryable matches = m_Locator.Logs; // Users filter if (usersFilter) matches = matches.Where(l => l.UserName == comboBoxUsers.Text); // Severity filter if (severityFilter) matches = matches.Where(l => l.Severity == comboBoxSeverity.Text); Logs = (from log in matches orderby log.EventTime descending select log).ToList(); 

Это создает запрос перед удалением базы данных. Команда не будет работать до конца .ToList () в конце.

Когда дело доходит до условного linq, я очень люблю шаблон фильтров и труб.
http://blog.wekeroad.com/mvc-storefront/mvcstore-part-3/

В основном вы создаете метод расширения для каждого случая фильтра, который принимает IQueryable и параметр.

 public static IQueryable HasID(this IQueryable query, long? id) { return id.HasValue ? query.Where(o => i.ID.Equals(id.Value)) : query; } 

Другой вариант – использовать что-то вроде PredicateBuilder, обсуждаемого здесь . Он позволяет писать код следующим образом:

 var newKids = Product.ContainsInDescription ("BlackBerry", "iPhone"); var classics = Product.ContainsInDescription ("Nokia", "Ericsson") .And (Product.IsSelling()); var query = from p in Data.Products.Where (newKids.Or (classics)) select p; 

Обратите внимание: я только получил это, чтобы работать с Linq 2 SQL. EntityFramework не реализует Expression.Invoke, который необходим для работы этого метода. У меня есть вопрос по этой проблеме.

Делая это:

 bool lastNameSearch = true/false; // depending if they want to search by last name, 

имея это в заявлении where :

 where (lastNameSearch && name.LastNameSearch == "smith") 

означает, что при создании окончательного запроса, если lastNameSearch является false запрос полностью опустит любой SQL для поиска по фамилии.

Это не самая красивая вещь, но вы можете использовать выражение lambda и передать свои условия в случае необходимости. В TSQL я делаю много следующих действий, чтобы сделать параметры необязательными:

WHERE Поле = @FieldVar ИЛИ @FieldVar IS NULL

Вы можете дублировать один и тот же стиль со следующей лямбдой (пример проверки подлинности):

MyDataContext db = new MyDataContext ();

void RunQuery (строка param1, строка param2, int? param3) {

Func checkUser = пользователь =>

((param1.Length> 0)? user.Param1 == param1: 1 == 1) &&

((param2.Length> 0)? user.Param2 == param2: 1 == 1) &&

((param3! = null)? user.Param3 == param3: 1 == 1);

Пользователь foundUser = db.Users.SingleOrDefault (checkUser);

}

Недавно у меня было подобное требование, и в конце концов я нашел это в MSDN. Примеры CSharp для Visual Studio 2008

Классы, включенные в образец загрузки DynamicQuery, позволяют создавать динамические запросы во время выполнения в следующем формате:

 var query = db.Customers. Where("City = @0 and Orders.Count >= @1", "London", 10). OrderBy("CompanyName"). Select("new(CompanyName as Name, Phone)"); 

Используя это, вы можете построить строку запроса динамически во время выполнения и передать ее в метод Where ():

 string dynamicQueryString = "City = \"London\" and Order.Count >= 10"; var q = from c in db.Customers.Where(queryString, null) orderby c.CompanyName select c; 

Я решил это с помощью метода расширения, чтобы LINQ можно было условно включить в середине выражения жидкости. Это устраняет необходимость разложения выражения с помощью операторов if .

.If() метод расширения:

 public static IQueryable If( this IQueryable source, bool condition, Func, IQueryable> branch) { return condition ? source : branch(source); } 

Это позволяет сделать это:

 return context.Logs .If(filterBySeverity, q => q.Where(p => p.Severity == severity)) .If(filterByUser, q => q.Where(p => p.User == user)) .ToList(); 

Просто используйте оператор C # &&:

 var items = dc.Users.Where(l => l.Date == DateTime.Today && l.Severity == "Critical") 

Редактировать: Ах, нужно читать более внимательно. Вы хотели знать, как условно добавлять дополнительные предложения. В этом случае я понятия не имею. 🙂 То, что я бы сделал, это просто подготовить несколько запросов и выполнить правильный, в зависимости от того, что мне нужно.

Вы можете использовать внешний метод:

 var results = from rec in GetSomeRecs() where ConditionalCheck(rec) select rec; ... bool ConditionalCheck( typeofRec input ) { ... } 

Это будет работать, но не может быть разбито на деревья выражений, что означает, что Linq to SQL будет запускать контрольный код для каждой записи.

В качестве альтернативы:

 var results = from rec in GetSomeRecs() where (!filterBySeverity || rec.Severity == severity) && (!filterByUser|| rec.User == user) select rec; 

Это может работать в деревьях выражений, что означает, что Linq to SQL будет оптимизирован.

Ну, как я думал, вы могли бы включить условия фильтра в общий список Predicates:

  var list = new List { "me", "you", "meyou", "mow" }; var predicates = new List>(); predicates.Add(i => i.Contains("me")); predicates.Add(i => i.EndsWith("w")); var results = new List(); foreach (var p in predicates) results.AddRange(from i in list where p.Invoke(i) select i); 

Это приводит к списку, содержащему «меня», «meyou» и «косить».

Вы можете оптимизировать это, выполнив foreach с предикатами в совершенно другой функции, которая ORs все предикаты.

  • Что я могу сделать, чтобы разрешить исключение «Row not found or changed» в LINQ to SQL в базе данных SQL Server Compact Edition?
  • Метаданные не были загружены с использованием MetadataType
  • Создание classа Entity для изменений
  • Почему Entity Framework не сможет использовать ToString () в операторе LINQ?
  • LINQ to SQL с использованием GROUP BY и COUNT (DISTINCT)
  • Linq to Sql: множественные левые внешние соединения
  • Общее выражение таблицы (CTE) в linq-to-sql?
  • Как выполнить объединение в linq в sql с синтаксисом метода?
  • LINQ to SQL: несколько объединений в нескольких столбцах. Это возможно?
  • Как сравнивать только даты без времени в типах DateTime в Linq to SQL с Entity Framework?
  • LINQ - Left Join, Group By и Count
  • Interesting Posts

    Настройте гостевую гостевую систему Virtualbox со статическим IP-адресом, SSH и доступом в Интернет от хоста

    Есть ли простой способ разделить NSString на массив символов?

    Как динамически запрашивать базу данных комнаты во время выполнения?

    Как выйти из утилиты командной строки PostgreSQL: psql

    Условное форматирование ячейки на основе значения в 4 смежных ячейках

    Содержимое флэш-накопителя USB заменено одним ярлыком

    NetworkStream.ReadAsync с маркером отмены никогда не отменяет

    Назначение сочетания клавиш для конкретной конфигурации сборки Eclipse

    Как заменить текст на CSS?

    Требуется ли знак или нуль при добавлении 32-битного смещения к указателю для ABI x86-64?

    Полностью отключить UAC в Windows 10

    Есть ли встроенный метод сравнения коллекций?

    ASP.NET MVC: создан ли controller для каждого запроса?

    Копирование файлов из контейнера Docker в хостинг

    Таинственная stacktrace в консоли разработчика Android (размер растрового изображения превышает 32 бит)

    Давайте будем гением компьютера.