2009-02-20 55 views
1

我有一些謂詞動態地建立了具有以下特徵的參數成函數通過搜索動態:使用LINQ和動態創建謂詞

Expression<Func<TblTableR, bool>> TableRPredicate, 
Expression<Func<TblTableN, bool>> suspectNamesPredicate, 
Expression<Func<TblTableS, bool>> TableSPredicate, 
Expression<Func<TblTableI, bool>> suspectTableIPredicate, 

我試圖使用查詢如下:

var registries = (from r in db.TblTableR.Where(TableRPredicate) 
join s in db.TblTableS.Where(TableSPredicate) 
     on r.TblTableRID equals s.TblTableSTableRID into ss 
from suspects in ss.DefaultIfEmpty() 
    join si in db.TblTableI.Where(suspectTableIPredicate) 
     on suspects.TblTableSIndexCardID equals si.TblTableIID into sisi 
    from suspectTableI in sisi.DefaultIfEmpty() 
    join sn in db.TblTableN.Where(suspectNamesPredicate) 
     on suspectTableI.TblTableIID equals sn.TblTableNIndexCardID into snsn 
    from suspectNames in snsn.DefaultIfEmpty() 
    select r.TblTableRID).Distinct(); 

這有把任何產生「其中」條款列入JOIN語句如結果:

left outer join tblTableI on tblTableITableRID = tblTableRID 
    AND (expression created by predicate) 

實際發生的是最終創建的SQL不正確。它創建以下類型的SQL

select * from table1 left outer join table2 on field1 = field2 
    AND field3 = 'CRITERIA' 

的正是這一點,子句,這是問題的結束 - 結束了返回太多行。從本質上講,我希望將where子句放入聲明中,而不是將附加條件粘到連接中。

事情是這樣的:

select * from table1 left outer join table2 on field1 = field2 
    WHERE field3 = 'CRITERIA' 

我試圖在如下添加一個WHERE子句:

... 
... 
... 
select r.TblTableRID).Where(TableRPredicate).Distinct(); 

但由於每個謂詞的泛型參數不會編譯。

如果我修改我的LINQ查詢以僅從一個表中進行選擇並使用謂詞,則會正確生成WHERE子句。

任何想法?

回答

1

(編輯後澄清)

步驟1;更改最終選擇以將全部三個實體選擇爲匿名類型;對我來說(測試Northwind),即:

select new {emp, cust, order}; 

第2步;使用我在下面添加的擴展方法將您的過濾器應用於此;對我來說這個過濾看起來像:

var qry2 = qry.Where(x => x.emp, employeeFilter) 
      .Where(x => x.cust, custFilter) 
      .Where(x => x.order, orderFilter); 

第3步;現在從這個過濾查詢選擇你真正想要的實體/實體:

var data = qry2.Select(x => x.order) 

而這裏的擴展方法:

static IQueryable<T> Where<T,TValue>(
    this IQueryable<T> source, 
    Expression<Func<T, TValue>> selector, 
    Expression<Func<TValue, bool>> predicate) 
{ 
    var row = Expression.Parameter(typeof (T), "row"); 
    var member = Expression.Invoke(selector, row); 
    var lambda = Expression.Lambda<Func<T, bool>>(
     Expression.Invoke(predicate, member), row); 
    return source.Where(lambda); 
} 
+0

馬克, 我已經更新了後讓事情更清楚一點。 Peter – 2009-02-20 10:00:26