2014-01-24 72 views
1

這是我的場景:我需要從一個實體中使用「OR」查詢對鏈接實體中的屬性提取數據。執行一個linq樹表達式到這裏

這是我的實體:

public class Dealer 
{ 
    public virtual int id{get;set;} 
    public virtual string name{get;set;} 
    public virtual IList<Car> Cars{get;set;} 
} 

public class Car 
{ 
    public virtual int id{get;set;} 
    public virtual string name{get;set;} 
    public virtual int kw{get;set;} 
} 

例子:我想提取與98千瓦或百千瓦汽車所有經銷商。 SQL示例:

SELECT Dealers.* FROM Dealers INNER JOIN Cars ON Cars.IdDealer = Dealers.Id WHERE Cars.kw = 98 OR Cars.kw = 100 

我試圖用表達式樹,但我不知道如何使用它們。 我嘗試這樣做:

var dealers = Session.Linq<Dealers>(); 
ParameterExpression pe = Expression.Parameter(typeof(int), "kw"); 
Expression tot = null; 
var powers = new int[2]{98, 100}; 

for (var i = 0; i < powers.Length; i++) 
{ 
    Expression right = Expression.Constant(int.Parse(powers[i])); 
    if (i > 0) 
     tot = Expression.Or(tot, Expression.Equal(pe, right)); 
    else 
     tot = Expression.Equal(pe, right); 
} 
dealers = dealers.Where(x => x.Cars.Any(Expression.Lambda<Func<Cars, bool>>(tot, null))); 

,但我得到的最後一行,這些編譯器錯誤,我試圖執行的表達式:

  • 無法轉換lambda表達式類型string,因爲它不是一個委託類型
  • System.Collections.Generic.IList<Cars>不包含Any的定義和最佳擴展方法重載System.Linq.Enumerable.Any(System.Collections.Generic.IEnumerable,System.Func)有一些無效參數
  • 參數2:不能從System.Linq.Expressions.Expression<System.Func<Cars,bool>>轉換爲System.Func<Cars,bool>

有什麼建議?

+0

什麼「編譯器錯誤」? –

+0

我可以提出一些建議,可能會或可能不會受到歡迎。在我看來,你應該避免在開放環境中以這種方式使用RAW表達式。我會衷心建議你採用更加封閉的方法,並看看像albahari predicatebuilder:http://www.albahari.com/nutshell/predicatebuilder.aspx會爲你節省很多挫折。在頁面上的一些很好的工作示例 –

+0

@KonradMorawski添加了有問題的錯誤列表 – Albirex

回答

0

演員Expression.Lambda來

Expression<Func<Car, bool>> 

的結果,你需要在參數表達來傳遞:

x.Cars.Any((Expression<Func<Car, bool>>)Expression.Lambda<Func<Cars, bool>>(tot, pe)) 
2

按照我留下的評論:

。 ..我可以提出一個可能會或可能不會滿意的建議。在我看來,你應該避免在開放環境中以這種方式使用RAW表達式。我會衷心建議你採用更加封閉的方法,看看像albahari predicatebuilder: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); 
} 

等等。因此,你可以建立非常複雜的語句將所有的內部隱藏起來。這很有意義,特別是如果您現在或將來可能有更多的初級開發人員在開發代碼。我強烈要求你放縱自己的好奇心,並且徘徊於這個環節,並從那裏獲得更好的感受。

1

試圖改變這樣的

var dealers = Session.Linq<Dealers>(); 
ParameterExpression pe = Expression.Parameter(typeof(Car), "c"); 
var kw = Expression.Property(pe, "kw"); 
var powers = new string[2]{"98", "100"}; 

Expression tot = powers.Select(p=>Expression.Constant(int.Parse(p))) 
         .Select(p=>Expression.Equal(kw,p)) 
         .Aggregate((a,b)=>Expresion.Or(a,b)); 

還需要改變你的Cars聲明IEnumerable<Car>IQueriable<Car>

如果IEnumerable<Car>然後調用它像

dealers = dealers.Where(x => x.Cars.Any(Expression.Lambda<Func<Cars, bool>>(tot, pe).Compile())); 

如果代碼然後稱之爲

dealers = dealers.Where(x => x.Cars.Any(Expression.Lambda<Func<Cars, bool>>(tot, pe)));