Динамический встроенный Linq to SQL Query - PullRequest
1 голос
/ 18 декабря 2009

Я хочу построить общее окно поиска, используя linq to sql.

Вот что я пытался сделать:

class SearchWindow<T> : Form : Where T: class
{
    public SearchWindow(Func<T, string> codeSelector, 
                        Func<T, string> nameSelector)
    {
        var db = new DataContext();
        var table = db.GetTable<T>();
        var query = from item in table where 
                        codeSelector(item).Contains(someText) &&
                        nameSelector(item).Contains(someOtherText)
                    select item;
    }
}

И я пытался использовать это как:

var searchWindow = new SearchWindow<SomeTable>(x => x.CodeColumn, 
                                               y => y.NameColumn).Show();

Бад, к сожалению, это не работает, я читал о деревьях выражений, поэтому я попытался сделать это с ними, и я получил:

public SearchWindow(codeColumn, nameColumn) 
{
    Table<T> table = db.GetTable<T>();
    var instanceParameter = Expression.Parameter(typeof(T), "instance");
    var methodInfo = typeof(string).GetMethod("Contains", 
                                              new Type[] { typeof(string) });
    var codigoExpression = Expression.Call(Expression.Property(instanceParameter, 
                                               codeColumn), 
                                           methodInfo, 
                                           Expression.Constant("someText", 
                                               typeof(string)));
    var nombreExpression = Expression.Call(Expression.Property(instanceParameter, 
                                               nameColumn), 
                                           methodInfo, 
                                           Expression.Constant("someOtherText", 
                                               typeof(string)));
    var predicate = Expression.Lambda<Func<T, bool>>(
         Expression.And(codigoExpression, nombreExpression), instanceParameter);
    var query = table.Where(predicate);
}

И чтобы использовать его, мне нужно сделать:

new SearchWindow<SomeTable>("codeColumn", "nameColumn");

Но мне не нравится подход к необходимости вводить имена столбцов в виде строки, есть ли способ сделать это способом, подобным моему первому подходу (чтобы иметь смысл и строгую типизацию)?

Спасибо за вашу помощь.

Ответы [ 2 ]

2 голосов
/ 18 декабря 2009

Не проверено, но что-то вроде:

    static IQueryable<T> Search<T>(
        IQueryable<T> source,
        Expression<Func<T, string>> codeSelector, 
        Expression<Func<T, string>> nameSelector,
        string code, string name)
    {

        var row = Expression.Parameter(typeof(T), "row");
        var body = Expression.AndAlso(
            Expression.Call(
                Expression.Invoke(codeSelector, row),
                "Contains", null,
                Expression.Constant(code, typeof(string))),
            Expression.Call(
                Expression.Invoke(nameSelector, row),
                "Contains", null,
                Expression.Constant(name, typeof(string))));
        var lambda = Expression.Lambda<Func<T, bool>>(body, row);
        return source.Where(lambda);
    }

Вы передаете свою таблицу (GetTable<T>) как source и лямбда-символы для указания столбцов (x => x.CodeColumn / y => y.NameColumn и т. Д.).


Обновление; я надеюсь, что он будет работать и на LINQ-to-SQL:

        var data = new[] {
            new { Code = "abc", Name = "def"},
            new { Code = "bcd", Name = "efg"},
            new { Code = "ghi", Name = "jkl"}
        }.AsQueryable();

        var filtered = Search(data, x => x.Code, x => x.Name, "b", "f");
        var arr = filtered.ToArray();
0 голосов
/ 18 декабря 2009

Используйте PredicateBuilder - он сделает тяжелую работу за вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...