【问题标题】:Dynamic built Linq to SQL Query动态构建 Linq to SQL 查询
【发布时间】:2009-12-18 19:46:37
【问题描述】:

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

但我不喜欢需要将列名作为字符串输入的方法,有什么方法可以以类似于我的第一种方法的方式进行(以便具有智能感知和强类型)?

感谢您的帮助。

【问题讨论】:

  • 我认为缺少的部分是“Expression.Invoke”和“Expression.AndAlso”;我试图展示一个例子。

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


【解决方案1】:

未经测试,但类似:

    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&lt;T&gt;) 作为 source 传递,并使用 lambdas 来指示列 (x =&gt; x.CodeColumn / y =&gt; 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();

【讨论】:

    【解决方案2】:

    使用PredicateBuilder- 它会为您完成繁重的工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-17
      相关资源
      最近更新 更多