2009-05-11 4 views
46

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

У меня есть несколько десятков флажков на форме и я передаю их обратно, как: Словарь < строки, список < строки > > (Словарь < FIELDNAME, список < значение > >) на мой запрос 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; 
} 

ответ

49

alt text http://www.scottgu.com/blogposts/dynquery/step2.png

Вам нужно что-то вроде этого? Используйте the Linq Dynamic Query Library (примеры включают примеры).

За дополнительной информацией обращайтесь к ScottGu's blog.

+0

Существует портированная версия github (https://github.com/kahanu/System.Linq.Dynamic), которую я вношу и помогаю управлять. –

8

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

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); }); 
} 
1

Вы можете использовать метод расширения 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' являются объектами списка.

1

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

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

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

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

Как это расширение исходного кода, который вы можете найти на Scott Guthrie's Blog это позволит вам сделать что-то вроде этого:

enter image description here

и вещи, как это:

enter image description here

3

Я придумал решение, которое даже я могу понять ... используя метод «Содержит», вы можете целить столько ГДЕ, сколько вы как. Если 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); 
    } 
4

У меня есть аналогичный сценарий, где мне нужно добавлять фильтры на основе пользовательского ввода, и я связываю предложение 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); 
+0

Лучше всего подходит для моей потребности и прост в использовании. Спасибо. – user6121177

-1

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

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

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

+0

Ссылка на решение приветствуется, но, пожалуйста, убедитесь, что ваш ответ полезен без него: [добавить контекст вокруг ссылки] (// meta.stackexchange.com/a/8259), чтобы у ваших друзей-пользователей было некоторое представление о том, что это такое и почему он там, затем укажите наиболее релевантную часть страницы, на которую вы ссылаетесь, в случае недоступности целевой страницы. [Ответы, которые немного больше, чем ссылка, могут быть удалены.] (// stackoverflow.com/help/deleted-answers) – FelixSFD

+0

Я извиняюсь. Я здесь новичок. – KJM

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