2016-11-07 172 views
0

已閱讀其他類似問題的回覆,但我無法使用PredicateBuilder或複製它的源代碼。我想我在這裏讀到:Linq to Entities where條款

< https://blogs.msdn.microsoft.com/meek/2008/05/02/linq-to-entities-combining-predicates/

但我福利局,因與翻譯什麼我讀給我申請什麼麻煩。我創建了一個L2E查詢,並試圖串聯或條款追加到WHERE:

因此,作爲簡單的代碼片段(這將是一個與先前已經定義AND'd WHERE子句中):

if (firstParm == "realtor") 
    query = query.Where(x=> x.A == "realtor"); 

現在試圖OR:

if (secondParm == "clown") 
    // how to add this one as an OR to the above query: 
    query = query.OR(x=> x.fool == "clown"); 

我明白這也可以做到與聯盟,但對語法不明確:

query = query.Union(x=> x.fool == "clown"); // ?? 

我也提到:

Combining two expressions (Expression<Func<T, bool>>)

Unable to create a compound Expression<Func<string, bool>> from a set of expressions

但同樣,我是新來的LINQ,尤其是表達式樹,所以需要更多的FILLIN。

+0

您在使用PredicateBuilder麻煩?或者您不能將其用於其他原因? –

+0

我不能帶第三方軟件:-( – frododot

+0

Updated [my answer](http://stackoverflow.com/a/40459470/111794)。 –

回答

1

有兩種方法產生的表達式。

  1. 使用編譯器來做到這一點。

    Expression<Func<Person, bool>> = p => p.LastName.Contains("A"); 
    

    限制:可以產生這樣的唯一表達式是LambdaExpression實例。另外,提取表達的部分並與其他部分結合是相當複雜的。

  2. 使用靜態方法System.Linq.Expressions.Expression


爲了生成動態表達式,可以任一不同的編譯器生成的表達式之間選擇:或者

// using Record and Records as a placeholder for the actual record type and DbSet property 

Expression<Func<Record,bool>> expr; 
if (firstParam == "realtor") { 
    if (secondParam == "clown") { 
     expr = x => x.A == "realtor" || x.fool == "clown"; 
    } else { 
     expr = x => x.A == "realtor"; 
    } 
} else { 
    if (secondParam == "clown") { 
     expr = x => x.fool="clown"; 
    } else { 
     expr = x => false; 
    } 
} 

var ctx = new MyDbContext(); 
var qry = ctx.Records.Where(expr).Select(x => new {x.A, x.fool}); 

,可以使用靜態方法動態創建的表達:

(將using System.Linq.Expressions;using static System.Linq.Expressions.Expression;添加到文件頂部。)

Expression expr; 
var parameter = Parameter(typeof(Record)); 
if (firstParam == "realtor") { 
    expr = Equals(
     MakeMemberAccess(parameter, typeof(Record).GetProperty("A")), 
     Constant("realtor") 
    ); 
} 
if (secondParam == "clown") { 
    var exprClown = Equals(
     MakeMemberAccess(parameter, typeof(Record).GetProperty("fool")), 
     Constant("clown") 
    ); 
    if (expr == null) { 
     expr = exprClown; 
    } else { 
     expr = Or(expr, exprClown); 
    } 
} 

var lambda = Lambda<Func<Record,bool>>(expr, new [] {parameter}); 
var ctx = new MyDbContext(); 
var qry = ctx.Records.Where(lambda).Select(x => new {x.A, x.fool}); 

給定一個帶有類型在編譯時未知的查詢,因此任何變量引用它必須是IQueryable而已,而不是IQueryable<T>

IQueryable qry = ctx.GetQuery(); //dynamically built query here 
var parameter = Parameter(qry.ElementType); 
if (firstParam == "realtor") { 
    expr = Equals(
     MakeMemberAccess(parameter, qry.ElementType.GetProperty("A")), 
     Constant("realtor") 
    ); 
} 
if (secondParam == "clown") { 
    var exprClown = Equals(
     MakeMemberAccess(parameter, qry.ElementType.GetProperty("fool")), 
     Constant("clown") 
    ); 
    if (expr == null) { 
     expr = exprClown; 
    } else { 
     expr = Or(expr, exprClown); 
    } 
} 

var lambda = Lambda(expr, new [] {parameter}); 

//Since we don't have access to the TSource type to be used by the Where method, we have 
//to invoke Where using reflection. 
//There are two overloads of Queryable.Where; we need the one where the generic argument 
//is Expression<Func<TSource,bool>>, not Expression<Func<TSource,int,bool>> 
var miWhere = typeof(Queryable).GetMethods().Single(mi => { 
    mi.Name == "Where" && 
     mi.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetGenericArguments().Length == 2 
}); 

qry = miWhere.Invoke(null, new [] {qry, lambda}); 
+0

因爲我會比較一個查詢的屬性, m不清楚要爲上面的Record type寫些什麼typeT是由select創建的虛擬記錄,我試圖將WHERE OR子句連接到上面。希望這是有道理的:-) - newb – frododot

+0

@frododot你可以展示你如何創建你的查詢?你使用匿名類型還是其他? –

+0

它是匿名的:var query = from ... where ... select new {...} – frododot

0

對於或者你可以嘗試

if (secondParm == "clown") 
    { 
    query = query.Where(x=> x.fool == "clown" || x.fool==x.fool); 
    } 

OR

if (secondParm == "clown") 
    { 
    query = query.Where(x=> x.fool == "clown" || true); 
    }