动态构建Linq to SQL Query

时间:2009-12-18 19:46:37

标签: c# linq-to-sql expression-trees

我想使用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();

Bud悲伤地说,这不起作用,我读到了表达树,所以我试着和他们一起做,我得到了:

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 个答案:

答案 0 :(得分:2)

未经测试,但类似:

    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传递,并使用lambdas表示列(x => x.CodeColumn / y => y.NameColumn等)。


更新;在LINQ-to-Objects上进行测试,我希望它也适用于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();

答案 1 :(得分:0)

使用PredicateBuilder - 它会为你做繁重的工作。