2011-03-03 34 views
1

我們正在使用Dynamic Linq庫構建動態搜索表達式。我們遇到了一個問題,那就是如何使用動態linq庫構造具有一對多關係的導航屬性的lamba表達式。導航屬性上的動態Linq搜索表達式

我們有我們使用下面用含有陳述書

Person.Names.Select(FamilyName).FirstOrDefault() 

它的工作原理,但這裏有兩個問題。

  1. 它當然只選擇FirstOrDefault()名稱。我們希望它爲每個人使用所有名稱。

  2. 如果某人沒有名字,則Select會拋出異常。

這對定期查詢並不困難,因爲我們可以從語句中執行兩個操作,但lambda表達式更具挑戰性。

任何建議,將不勝感激。

EDIT- 附加代碼信息...非動態linq表達式看起來像這樣。

var results = persons.Where(p => p.Names.Select(n => n.FamilyName).FirstOrDefault().Contains("Smith")).ToList(); 

和類看起來像以下各項

public class Person 
{ 
public bool IsActive { get; set;} 

public virtual ICollection<Name> Names {get; set;} 
} 

public class Name 
{ 
public string GivenName { get; set; } 

public string FamilyName { get; set; } 

public virtual Person Person { get; set;} 
} 
+1

你可以發表由'FamilyName'表示的代碼嗎? – 2011-03-03 06:10:03

回答

2

我們散列出來,並做到了,但它是相當具有挑戰性。以下是我們如何進展到最終結果的各種方法。現在我們只需要重新思考我們的SearchExpression類是如何構建的......但這是另一回事。

1.等效查詢語法

var results = from person in persons 
from name in person.names 
where name.FamilyName.Contains("Smith") 
select person; 

2.等效lambda語法

var results = persons.SelectMany(person => person.Names) 
        .Where(name => name.FamilyName.Contains("Smith")) 
        .Select(personName => personName.Person); 

3.等效lambda語法與動態的LINQ

var results = persons.AsQueryable().SelectMany("Names") 
        .Where("FamilyName.Contains(@0)", "Smith") 
        .Select("Person"); 

注意事項 - 您必須將一個Contains方法添加到動態Linq庫。

編輯 - 或者使用只是一個選擇...更簡單...但它需要上述Contains方法添加。

var results = persons.AsQueryable().Where("Names.Select(FamilyName) 
            .Contains(@0", "Smith) 

我們最初試過這個,但遇到了可怕的'沒有適用的聚合方法Contains exists'。錯誤。我試圖讓SelectMany工作時解決了問題,因此我回到了Select方法。