2013-01-09 64 views
4

我有一些非常相似的LINQ查詢:同LINQ查詢連接,但在不同的條件

var city = "Hamburg"; 

var query1 = 
    from c in DB.Customers 
    join address in DB.Addresses on c.ID equals address.CustomerID 
    where address.City == city 
    select c; 

var query2 = 
    from c in DB.Customers 
    join address in DB.Addresses on c.ID equals address.CustomerID 
    where address.City.StartsWith(city) 
    select c; 

etc. 

我想用一個循環來創建查詢,以減少冗餘:

var city = "Hamburg"; 

var expressions = new Expression<Func<string, bool>>[] { 
    a => a == city, 
    a => a.StartsWith(city) 
}; 

for(int i = 1; i <= 2; i++) { 
    queries.Add(
     from c in DB.Customers 
     join address in DB.Addresses on c.ID equals address.CustomerID 
     where expressions[i](address.City) 
     select c 
     ); 
} 

但我不現在不知道如何創建表達式數組。任何想法?

+1

老實說,這看起來像存儲過程的工作。 – asawyer

+0

您的預期成果是什麼?一個清單,「我」列出? – Hogan

+0

@Hogan我期望'i'列表包含由不同表達式過濾的客戶。 – Dennis

回答

3
var city = "Hamburg"; 

// predicate should accept Address 
var expressions = new Expression<Func<Address, bool>>[] { 
    a => a.City == city, 
    a => a.City.StartsWith(city) 
}; 

foreach(var predicate in expressions) { 
    queries.Add(
     DB.Customers.Join(
      DB.Addresses.Where(predicate), // filtering here 
      c => c.ID, 
      a => a.CustomerID, 
      (c, a) => c) // return customer 
    )); 
} 
1

您可以將通用連接部分保存在通用查詢中。

var query = from c in DB.Customers 
     join address from DB.Addresses on c.ID equals address.CustomerID 
     select new {A=a, C=c}; 
var query1 = query.Where (item => item.A.temp == item.C.test).Select (item => item.C); 
var query2 = query.Where (item => item.A.temp2 == item.C.test2).Select (item => item.C); 
3

可以使用Join方法,而不是直接使用的查詢語法:

public IQueryable<Customer> FindCustomers(Expression<Func<Customer, Address, bool>> predicate) 
{ 
    return DB.Customers.Join(DB.Addresses, c => c.ID, a => d.CustomerID, (c, a) => new { Address = a, Customer = c}) 
     .Where(pair => predicate(pair.Address)) 
     .Select(pair => pair.Customer) 
} 

,或者你可以同時通過CustomerAddress

public IQueryable<Customer> FindCustomers(Expression<Func<Customer, Address, bool>> predicate) 
{ 
    return DB.Customers.Join(DB.Addresses, c => c.ID, a => d.CustomerID, (c, a) => new { Address = a, Customer = c}) 
     .Where(pair => predicate(pair.Customer, pair.Address)) 
     .Select(pair => pair.Customer) 
} 

,那麼你可以創建你陣列爲:

IQueryable<Customer>[] queries = expressions.Select(expr => FindCustomers(expr)).ToArray(); 
+0

謂詞應該接受地址 –

+0

問題是謂詞需要訪問地址的一個屬性,但是當我加入'(c,a)=> c'時,我只能在我的謂詞中使用客戶,或者我錯過了什麼? – Dennis

+0

@丹尼斯 - 我已經改變它使用「地址」,而不是「客戶」。 – Lee

1
var queries=(
    from f in 
     new Func<Address, bool>[] { 
      x => x.City==city, 
      x => x.City.StartsWith(city) 
      } 
    select 
     from c in DB.Customers 
     join address in DB.Addresses on c.ID equals address.CustomerID 
     where f(address) 
     select c 
    ).ToArray(); 
  1. 你正在創建一個expression array,這意味着你得到的畢竟一個expression array;你不需要讓代表expression array

  2. 你不需要foreach

  3. 如果您稍後添加更多表達式queries,然後更改ToArray()ToList()

  4. 如果你想使Func<Address, bool>修改你生成queries之前,然後爲其定義一個局部變量,並且僅替換它的Func<Address, bool>[]

+0

+1 - 100%linqy – Hogan

+0

謝謝。什麼是'協會獎金',我剛剛得到了通知。 –