Динамическое предложение WHERE в LINQ - программирование
Подтвердить что ты не робот

Динамическое предложение WHERE в LINQ

Каков наилучший способ собрать динамическое предложение WHERE в оператор LINQ?

У меня есть несколько десятков флажков в форме и передаю их обратно: Словарь < string, List <string → > (Dictionary < fieldName, List < values ​​ → ) в мой запрос LINQ.

public IOrderedQueryable<ProductDetail> GetProductList(string productGroupName, string productTypeName, Dictionary<string,List<string>> filterDictionary)
{
    var q = from c in db.ProductDetail
            where c.ProductGroupName == productGroupName && c.ProductTypeName == productTypeName
            // insert dynamic filter here
            orderby c.ProductTypeName
            select c;
    return q;
}
4b9b3361

Ответ 2

Вы также можете использовать PredicateBuilder из LinqKit для объединения нескольких типов лямбда-выражений с использованием Or или And.

http://www.albahari.com/nutshell/predicatebuilder.aspx

Ответ 3

Простой подход может быть, если ваши столбцы имеют простой тип, например String

public static IEnumerable<MyObject> WhereQuery(IEnumerable<MyObject> source, string columnName, string propertyValue)
{
   return source.Where(m => { return m.GetType().GetProperty(columnName).GetValue(m, null).ToString().StartsWith(propertyValue); });
}

Ответ 4

Я придумал решение, которое даже я могу понять... используя метод "Содержит", вы можете объединить столько ГДЕ, сколько захотите. Если WHERE является пустой строкой, она игнорируется (или оценивается как выбор всех). Вот мой пример объединения двух таблиц в LINQ, применения множественных предложений и заполнения класса модели для возврата в представление. (это выбор всех).

public ActionResult Index()
    {
        string AssetGroupCode = "";
        string StatusCode = "";
        string SearchString = "";

        var mdl = from a in _db.Assets
                  join t in _db.Tags on a.ASSETID equals t.ASSETID
                  where a.ASSETGROUPCODE.Contains(AssetGroupCode)
                  && a.STATUSCODE.Contains(StatusCode)
                  && (
                  a.PO.Contains(SearchString)
                  || a.MODEL.Contains(SearchString)
                  || a.USERNAME.Contains(SearchString)
                  || a.LOCATION.Contains(SearchString)
                  || t.TAGNUMBER.Contains(SearchString)
                  || t.SERIALNUMBER.Contains(SearchString)
                  )
                  select new AssetListView
                  {
                      AssetId = a.ASSETID,
                      TagId = t.TAGID,
                      PO = a.PO,
                      Model = a.MODEL,
                      UserName = a.USERNAME,
                      Location = a.LOCATION,
                      Tag = t.TAGNUMBER,
                      SerialNum = t.SERIALNUMBER
                  };


        return View(mdl);
    }

Ответ 5

У меня есть аналогичный сценарий, когда мне нужно добавить фильтры на основе пользовательского ввода, и я связываю предложение where.

Вот пример кода.

var votes = db.Votes.Where(r => r.SurveyID == surveyId);
if (fromDate != null)
{
    votes = votes.Where(r => r.VoteDate.Value >= fromDate);
}
if (toDate != null)
{
    votes = votes.Where(r => r.VoteDate.Value <= toDate);
}
votes = votes.Take(LimitRows).OrderByDescending(r => r.VoteDate);

Ответ 7

Вы можете использовать метод расширения Any(). Для меня, похоже, работает.

XStreamingElement root = new XStreamingElement("Results",
                from el in StreamProductItem(file)
                where fieldsToSearch.Any(s => el.Element(s) != null && el.Element(s).Value.Contains(searchTerm))
                select fieldsToReturn.Select(r => (r == "product") ? el : el.Element(r))
            );
            Console.WriteLine(root.ToString());

Где 'fieldsToSearch' и 'fieldsToReturn' являются объектами списка.

Ответ 8

Этот проект на CodePlex имеет то, что вы хотите.

System.Linq.Dynamic - http://dynamiclinq.codeplex.com/

Описание проекта

Расширяет System.Linq.Dynamic для поддержки выполнения Лямбда-выражений, определенных в строке с Entity Framework или любым провайдером, поддерживающим IQueryable.

Поскольку это расширение исходного кода, вы можете найти в Scott Guthrie Blog, это позволит вам делать такие вещи:

enter image description here

И такие вещи:

enter image description here

Ответ 9

Это решение, с которым я столкнулся, если кому-то это интересно.

https://kellyschronicles.wordpress.com/2017/12/16/dynamic-predicate-for-a-linq-query/

Сначала мы идентифицируем один тип элемента, который нам нужно использовать (из TRow As DataRow), а затем идентифицируем "источник", который мы используем, и привязываем идентификатор к этому источнику ((источник As TypedTableBase (Of TRow)). должен указать предикат или предложение WHERE, которое будет передано (предикат As Func (Of TRow, Boolean)), который либо будет возвращен как истинный, либо false. Затем мы определяем, как мы хотим, чтобы возвращаемая информация упорядочивалась (OrderByField As String). Затем наша функция вернет EnumerableRowCollection (Of TRow), нашу коллекцию datarows, которая удовлетворяет условиям нашего предиката (EnumerableRowCollection (Of TRow)). Это базовый пример. Конечно, вы должны убедиться, что ваше поле заказа не работает содержат нули или правильно обработали эту ситуацию и убедитесь, что имена столбцов (если вы используете сильно типизированный источник данных, не обращайте на это внимания, он переименует столбцы для вас) являются стандартными.