Динамическое предложение where в LINQ to Objects - PullRequest
0 голосов
/ 08 января 2010

Я знаю, что есть много примеров этого в Интернете, но я не могу заставить это работать.

Позвольте мне попытаться настроить это, у меня есть список пользовательских объектов, которые мне нужно ограничить диапазоном значений.

У меня есть переменная сортировки, которая изменяется в зависимости от некоторых действий в пользовательском интерфейсе, и мне нужно обрабатывать объект по-разному в зависимости от этого.

Вот мой объект:

MyObject.ID - Just an identifier
MyObject.Cost - The cost of the object.
MyObject.Name - The name of the object.

Теперь мне нужно отфильтровать это на основе диапазона стоимости, поэтому у меня будет что-то похожее на это, учитывая, что я могу ограничить любым из моих двух нижних свойств.

var product = from mo in myobject 
              where mo.Cost <= 10000

или

var product = from mo in myobject
              where mo.Name equals strName

Теперь у меня есть динамический linq в моем проекте, но я не понимаю, как заставить его работать на самом деле, поскольку, когда я делаю некоторые примеры, я получаю только:

Func<Tsourse>bool> predicate

как опция.

Обновление: Я пытаюсь найти решение, которое поможет мне объективировать мой код, так как сейчас много копий и вставок для моих запросов linq.

Обновление 2: Есть ли очевидная разница в производительности между:

var product = from mo in myobject 
... a few joins ...
where mo.Cost <= 10000

и

var product = (from mo in myobject 
... a few joins ...)
.AsQueryable()
.Where("Cost > 1000")

Ответы [ 3 ]

2 голосов
/ 08 января 2010

Возможно, не отвечаю прямо на ваш вопрос, но здесь DynamicQuery не нужен. Вы можете написать этот запрос как:

public IEnumerable<MyObject> GetMyObjects(int? maxCost, string name)
{
    var query = context.MyObjects;
    if (maxCost != null)
    {
        query = query.Where(mo => mo.Cost <= (int)maxCost);
    }
    if (!string.IsNullOrEmpty(name))
    {
        query = query.Where(mo => mo.Name == name);
    }
    return query;
}

Если условия являются взаимоисключающими, просто измените второй if на else if.

Я использую этот шаблон все время. Что на самом деле означает «Динамический запрос», так это сочетание чистого SQL с Linq; на самом деле это не очень помогает в создании условий на лету.

1 голос
/ 08 января 2010
using System.Linq;

var products = mo.Where(x => x.Name == "xyz");

var products = mo.Where(x => x.Cost <= 1000);

var products = mo.Where(x => x.Name == "xyz" || x.Cost <= 1000);
1 голос
/ 08 января 2010

Прочтите этот замечательный пост в DLINQ от ScottGu

Dynamic LINQ (Часть 1. Использование библиотеки динамических запросов LINQ)

Вам потребуется что-то вроде

var product = myobject.Where("Cost <= 10000");
var product = myobject.Where("Name = @0", strName);

Если вы скачали образцы, вам нужно найти файл Dynamic.cs в образце.Вам нужно скопировать этот файл в свой проект, а затем добавить using System.Linq.Dynamic; в класс, в котором вы пытаетесь использовать Dynamic Linq.

РЕДАКТИРОВАТЬ: Чтобы ответить на ваши изменения.Да, конечно, разница в производительности.Если вы заранее знаете варианты фильтров, я бы посоветовал записать их без использования DLINQ.

Вы можете создать свой собственный метод расширения следующим образом.

 public static class FilterExtensions
    {
        public static IEnumerable<T> AddFilter<T,T1>(this IEnumerable<T> list, Func<T,T1, bool> filter,  T1 argument )
        {
            return list.Where(foo => filter(foo, argument) );
        }
    }

Затем создайте свои методы фильтрации.

        public bool FilterById(Foo obj, int id)
        {
            return obj.id == id;
        }

        public bool FilterByName(Foo obj, string name)
        {
            return obj.name == name;
        }

Теперь вы можете использовать его на IEnumerable<Foo>очень легко.

    List<Foo> foos = new List<Foo>();
    foos.Add(new Foo() { id = 1, name = "test" });
    foos.Add(new Foo() { id = 1, name = "test1" });
    foos.Add(new Foo() { id = 2, name = "test2" });

    //Example 1
    //get all Foos's by Id == 1
    var list1 = foos.AddFilter(FilterById, 1);

    //Example 2
    //get all Foo's by name ==  "test1"
    var list2 = foos.AddFilter(FilterByName, "test1");

    //Example 3
   //get all Foo's by Id and Name
   var list1 = foos.AddFilter(FilterById, 1).AddFilter(FilterByName, "test1");
...