2011-11-07 31 views
2

我試着按照要求在查詢中連接4個表。因爲我想動態地在where子句中添加條件,所以,我現在可以爲2表查詢做到這一點。但是這4個表連接在這裏是複雜的連接。爲了延長我使用下面的代碼的功能添加動態where子句:動態LINQ表達式查詢,得到問題

public static class Extensions 
    { 
     public static IQueryable<T> AddEqualityCondition<T, V>(this IQueryable<T> queryable, 
      string propertyName, V propertyValue) 
     { 
      ParameterExpression pe = Expression.Parameter(typeof(T), "p"); 

    IQueryable<T> x = queryable.Where<T>(Expression.Lambda<Func<T, bool>>(Expression.Equal(Expression.Property(pe, typeof(T).GetProperty(propertyName)), Expression.Constant(propertyValue, typeof(V)), false, typeof(T).GetMethod("op_Equality")), new ParameterExpression[] { pe })); 
      return (x); 
     } 
    } 

// 我的代碼添加這些條件:

Query is: 
var agrs = (from agr in _dbContext.Agreements 
           join amdv in _dbContext.AgreementMetaDataValues on agr.AgreementID equals amdv.AgreementID 
           join emd in _dbContext.EntityMetadatas on amdv.AttributeId equals emd.AttributeId 
           join et in _dbContext.Entities on agr.EntityID equals et.EntityId 
           select new agr, amdv,emd }); 

//Add dynamically where conditions: 
agrs = agrs.AddEqualityCondition("?????", "A83C82C5-F9D6-4833-A234-EBB5D971280C"); 

這是工作2表連接不超過那。因爲在複雜的查詢中它正在生成Annonymouse對象。所以 所以我需要通過什麼來代替「??????」分數...?通常需要將屬性名稱作爲「agr.AgreementId」傳遞,但這裏它將擴展類中的表達式作爲「Value Canot be Null:propertyName」引發。 需要此指導的更多指導...

+2

那豈不是更容易簡單地使用:'AGRS = agrs.Where(X => x.agr.AgreementId ==「A83C82C5-F9D6-4833-A234- EBB5D971280C「);'? –

+1

我相信Marc的評論是答案,因爲查詢將在以後開始使用它的結果(例如遍歷它們)時生成和執行。在此之前,您可以根據需要添加任意數量的where子句。 –

回答

5

我想你可能要考慮像(作爲一個額外的過載):

public static IQueryable<T> AddEqualityCondition<T, V>(
    this IQueryable<T> queryable, 
    Expression<Func<T, V>> selector, V propertyValue) 
{ 
    var lambda = Expression.Lambda<Func<T,bool>>(
     Expression.Equal(
      selector.Body, 
      Expression.Constant(propertyValue, typeof(V)), 
      false, typeof(T).GetMethod("op_Equality")), 
     selector.Parameters); 
    return queryable.Where(lambda);   
} 

和使用:

agrs = agrs.AddEqualityCondition(x => x.agr.AgreementId, 
      "A83C82C5-F9D6-4833-A234-EBB5D971280C"); 
然而

!這是很容易,只需使用:

agrs = agrs.Where(x => x.agr.AgreementId == 
      "A83C82C5-F9D6-4833-A234-EBB5D971280C"); 
+0

這是完美的!多謝,夥計。以及如果我想獲得基於x.agr.AgreementId的獨特記錄? –

+0

@Red你不能明確地得到「[某些成員]不同」,因爲最終SQL並不真正支持這一點。如果這是** LINQ-to-Objects **,則可以**輕鬆地寫入** DistinctBy,但如果這是LINQ-to-SQL或EF,則不能。如果你不希望有很多的蠢事,你可以通過本地獲取並應用截然不同的東西。 –

+1

@Red一個基本的LINQ到對象實現可能如下所示:'public static IEnumerable DistinctBy (此IEnumerable 源,Func 選擇器){var seen = new HashSet (); foreach(源中的var項)if(seen.Add(selector(item)))yield return item; }' –