2012-03-21 216 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(); 
    }