2012-03-21 85 views
3

转换在哪里我想去从从LINQ子句动态LINQ

 var selectData = (from i in data 
          where i.Name == "Bob1" 
          select i); 

 var selectData = (from i in data 
          select i).Where("Name==Bob1"); 

我已经试过各种方法(AsQueryableWhere<SomeData>),但不能得到第二表格来编译。

我没有掌握C#的通用扩展方法。 <Tsource>对我来说没有意义,所以这可能是问题所在。此外,我不明白当intellisense只显示.Where<>(通用)时,为什么我可以输入.Where()。我希望看到没有通用符号的第二个Where ......唉,我没有。

public class SomeData 
{ 
    public string Name { get; set; } 
    public string Address { get; set; } 
} 

UPDATE
似乎有一些混乱,如何在哪里()可以使用的可能是我的错。请参阅related问题。根据这个答案,where子句中的属性名称是完全合法的。我需要财产保持一个字符串。如果这意味着需要动态LINQ,那就这样吧......这就是我所需要的。

+0

这似乎与另一篇文章相似。也许这将帮助 [LINQ - 动态WHERE子句?] [1] [1]:http://stackoverflow.com/questions/848415/linq-dynamic-where-clause – 2012-03-21 18:06:56

+0

你需要动态查询你的属性名称?你能证实这一点吗? – payo 2012-03-21 18:07:04

+0

我还是不明白。如果你正在寻找如何做动态Linq,你已经在[你问的其他问题](http://stackoverflow.com/questions/9505189/dynamically-generate-linq-queries)上引用的答案还没有也回答这个问题? – 2012-03-21 18:10:15

回答

2

有了你的帮助,我已经设法让转换功能。

  1. 安装动态LINQ(我用的NuGet。对于System.Linq.Dynamic网上搜索)
  2. 添加using System.Linq.Dynamic
  3. 查询应该是这样的形式

    var selectData = (from i in data 
             select i).AsQueryable().Where("Name = @0","Bob1");//@0 is called an identifier. "Name = Bob1" straight up fails. 
    
  4. 安装ScottGU的C# sample library的。 ..它有助于。 (VB)(Original Post

1

UPDATE

我最初误解了这个问题;该问题的解决方案是下载Dynamic Linq并引用它。我将在下面留下我的回答,以解答有关通用扩展方法的问题。


var selectData = (from i in data 
    select i).Where(d => d.Name=="Bob1"); 

但是,为什么不这样:

var selectData = data.Where(d => d.Name=="Bob1"); 

至于在哪里,有没有这样的事情 “非一般” 的版本。在上面的调用中,泛型方法的类型参数是隐式的;已经推断出由编译器,这正是编译调用,因为它会编译这个:

var selectData = data.Where<SomeData>(d => d.Name=="Bob1"); 

也许草图实现Where方法将有助于减少对TSource参数你的困惑:

public static IEnumerable<TSource> Where(this IEnumerable<TSource> source, Func<TSource, bool> predicate) 
{ 
    foreach (TSource item in source) 
     if (predicate(item)) 
      yield return item; 
} 

TSource是您正在查询的序列的元素类型。这也是结果序列的元素类型。

编译器需要知道是什么类型至少有两个方面的原因:

首先,我们需要调用每个元素的功能,以确定是否将其纳入结果序列。编译器必须知道参数predicate可以安全地接受TSource类型的参数。

第二个原因在这种情况下有点微不足道; item必须与TSource分配兼容,因为它在yield return语句中使用。当然它是兼容的,因为它属于同一类型。

+0

我不能那样做。我需要该属性作为一个字符串。 – 2012-03-21 18:02:47

+0

你是什么意思“需要财产作为一个字符串”?该属性*是*一个字符串。你的意思是你想选择属性的值作为一个字符串?如果是这样,该值将是“Bob1”。如果你描述了'selectData'的期望值,那么它可能有助于澄清。 – phoog 2012-03-21 18:06:57

+0

@ P.Brian.Mackey你的意思是你想要在运行时指定要查询的属性,方法是将它的名称作为字符串传递给方法? – phoog 2012-03-21 18:14:43

2
var selectData = (from i in data 
        select i).Where(datum => datum.Name == "Bob1"); 

Where方法接受委托,而不是字符串,所以你需要一个委托或lambda通过。

编辑:根据您对其他答案之一的评论,您需要使用Reflection来使属性值查找变为动态。

编辑:看起来像你需要分别为动态Linq库download the source code

+0

如果是这样的话,请解释这个其他相关答案:http://stackoverflow.com/questions/9505189/dynamically-generate-linq-queries – 2012-03-21 18:04:27

+1

@ P.Brian.Mackey:这使用动态Linq。你当然可以探索,但这不是你问你的问题。 – 2012-03-21 18:05:38

+0

所以,我假设动态LINQ是我需要下载和参考的附加组件吗? – 2012-03-21 18:10:03

0

我相信这是你要找的内容:

http://www.albahari.com/nutshell/predicatebuilder.aspx

IQueryable<Product> SearchProducts (params string[] keywords) 
{ 
    var predicate = PredicateBuilder.False<Product>(); 

    foreach (string keyword in keywords) 
    { 
    string temp = keyword; 
    predicate = predicate.Or (p => p.Description.Contains (temp)); 
    } 
    return dataContext.Products.Where (predicate); 
} 

源代码

using System; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Collections.Generic; 

public static class PredicateBuilder 
{ 
    public static Expression<Func<T, bool>> True<T>() { return f => true; } 
    public static Expression<Func<T, bool>> False<T>() { return f => false; } 

    public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1, 
                 Expression<Func<T, bool>> expr2) 
    { 
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression>()); 
    return Expression.Lambda<Func<T, bool>> 
      (Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters); 
    } 

    public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1, 
                 Expression<Func<T, bool>> expr2) 
    { 
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression>()); 
    return Expression.Lambda<Func<T, bool>> 
      (Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters); 
    } 
} 
0

下面是一个使用表达式目录树,以一些简单的代码做你想做的事。这只适用于针对该特定类型的Property ==“...”查询。你当然可以修改它,并根据需要进行通用化。

public void Test() 
    { 
     List<SomeData> data = new List<SomeData>(); 
     data.Add(new SomeData("Mark", "Ledgewood Drive")); 
     data.Add(new SomeData("Tim", "Sumpter Drive")); 
     data.Add(new SomeData("Sean", "Leroy Drive")); 
     data.Add(new SomeData("Bob", "Wilmington Road")); 
     data.Add(new SomeData("Sean", "Sunset Blvd")); 

     List<SomeData> result = data.Where(BuildExpression("Name", "Mark")).ToList(); 
     List<SomeData> result2 = data.Where(BuildExpression("Address", "Wilmington Road")).ToList(); 
    } 

    private Func<SomeData, bool> BuildExpression(string propertyName, string value) 
    { 
     ParameterExpression pe = Expression.Parameter(typeof(SomeData), "someData"); 
     Expression left = Expression.Property(pe, propertyName); 
     Expression right = Expression.Constant(value); 
     BinaryExpression binary = Expression.Equal(left, right); 
     Expression<Func<SomeData, bool>> lambda = Expression.Lambda<Func<SomeData, bool>>(binary, pe); 
     return lambda.Compile(); 
    }