2009-08-20 73 views
4

我有一個項目,要求我做這樣的BIG搜索引擎,但這都是動態的。我的意思是我可以有大約0到9個主要的「組」,它們在內部具有諸如「OR」或「AND」的「where」的無限可能性。我們首先想到的是使用Dynamic Linq,它爲構建動態查詢提供了一個很好的選擇。所有這些使用EF與自制包裝。集合上的動態LINQ?

問題: 我無法訪問「收集」。我的意思是,我可以很容易地訪問一個引用的對象(如Customer.State.StateName =「New-York」或Custoemr.State.StateName =「Quebec」),但我找不到方法來訪問類似:「Customer.Orders.OrderID = 2或Customer.Orders.OrderID = 3」。我可以很容易地弄清楚它是因爲它的一個集合,但我怎麼能做到這一點?

請幫我一把!

**對不起,我的英語!


更新

我不清楚足夠多的,我認爲,對不起它由於IM法國...

我的問題了,因爲沒有什麼是一成不變的。它是一個候選人搜索引擎,用於將候選人放入企業中的recaruting compagny。在經理可以搜索候選人的頁面中,他可以通過以下方式「解析」:域名(工作),城市或許多其他用戶在註冊時填寫的內容。所有這些格式(如果它在SQL中):

WHERE(domaine.domainID = 3或domaine.domainID = 5或domaine.domainID = 23)AND(cities.cityID = 4,cities 。市= 32)[...]

所以無法與正常LINQ格式像這樣做:

Candidat.Domaines.Where(domain => domain.DomainID == 3 || domain.DomainID == 5 || domain.DomainID == 23); 

即使是在操作者paretheses是動態的( 「AND」 或「OR 「)!這就是爲什麼我們試圖使用Dynamic Linq,因爲它更加靈活。

希望它更容易理解我的問題......


更新2 這裏是我的方法

private string BuildDomainsWhereClause() { 
     StringBuilder theWhere = new StringBuilder(); 

     if (this.Domaines.NumberOfIDs > 0) { 
      theWhere.Append("("); 

      theWhere.Append(string.Format("Domaines.Where(")); 
      foreach (int i in this.Domaines.ListOfIDs) { 
       if (this.Domaines.ListOfIDs.IndexOf(i) > 0) { 
        theWhere.Append(string.Format(" {0} ", this.DispoJours.AndOr == AndOrEnum.And ? "&&" : "||")); 
       } 
       theWhere.Append(string.Format("DomaineId == {0}", i)); 
      } 
      theWhere.Append("))"); 
     } 

     return theWhere.ToString(); 
    } 

它的偉大工程,而不是它 「不會返回boolean值」。那我該怎麼辦? 錯誤:「預期類型爲'布爾'的表達式」。

在結束時,其返回是這樣的: 「(Domaines.Where(DomaineId == 2 & & DomaineId == 3 & & DomaineId == 4 & & DomaineId == 5))」這是添加到我的LINQ查詢:

var queryWithWhere = from c in m_context.Candidats.Where(WHERE) 
            select c; 

不要忘記,有像7或8更多「可能」添加的東西搜索...任何想法?

回答

5

你需要在這裏做什麼,建立一個Lambda表達式(更具體地說是一個Expression<Func<T, bool>>)。你不能使用字符串。你可以建立一個簡單的表達式所示:

ParameterExpression p = Expression.Parameter(typeof(Domaine), "domaine"); 
Expression<Func<Domaine, bool>> wherePredicate = 
    Expression.Lambda<Func<Domaine, bool>>(
    Expression.Or(
     Expression.Equal(
     Expression.Property(p, "DomainID"), 
     Expression.Constant(10)), 
     Expression.Equal(
     Expression.Property(p, "DomainID"), 
     Expression.Constant(11)) 
    ), p); 

domaine.DomainID = 10 || domaine.DomainID = 11

如果您需要手動執行此操作,則不易讀。

有一個全面運作的表達式解析器基於在MSDN代碼庫中C# Samples for Visual Studio 2008一個字符串你會真正做到這一點,下DynamicQuery的樣本。 (LinqDataSource控件在內部使用此示例的稍微修改版本。)

+0

非常感謝。它不完全是我所期望的,但它看起來很棒。我仍然需要一點點才能使它完美動態。但是,非常感謝,非常有用。 – 2009-08-20 14:58:01

1

假設客戶。訂單返回一個集合,這正是爲什麼你不能僅僅調用它的一個屬性。

爲了使用LINQ讓你要找的訂單,你需要知道在這種情況下,你可以做將訂單(或其他屬性):

Customer.Orders.Find(order => order.OrderID == 2); 

編輯:添加表達式查找ID 2或3這樣:

Customer.Orders.FindAll(order => order.OrderID == 2 || order.OrderID == 3); 
1

難道我的理解是正確的,這兩個客戶是一家集和訂單的集合,而國家(明顯)是一個屬性?

var q = from a in Customer 
    from b in a.Orders 
    where b.ID == 2 
       || b.ID == 3 
    select b; 

我想我會工作。

編輯

我做了部分類似的東西。它已經太長,不能確切知道我是怎麼做到的,但我可以告訴你,我是用

public static IQueryable<T> Where<T>(this IQueryable<T> source, string predicate, params object[] values); 

從DynamicQueryable類。

this.CountrySitesObject.Sites.AsQueryable().Where(w.WhereQuery, w.WhereParameters) 

(從我的代碼複製)。

+0

是的,它的效果很好。但是,當你不真正知道你需要搜索多少「b.Id」時。即使不是它的「||」或之間的「&&」。 – 2009-08-20 13:33:46

+0

我也會試試這個。但我在一個似乎可行的解決方案。我稍後會回來給你發消息。 – 2009-08-20 15:25:18

0

如果退後一步,詢問客戶想要做什麼。

Filter bug information. 

爲什麼不將數據導出爲ex​​cel或將excel指向SQL表。這不是很有趣,但你會在幾個小時內完成,而不是幾天或幾周。 :)

+0

是的,我知道!但我們認爲動態LINQ是做我們正在尋找... – 2009-08-20 13:30:21

3

最終,我已經完全按照我想要的方式。

private string BuildDomainsWhereClause() { 
     StringBuilder theWhere = new StringBuilder(); 

     if (this.Domains.NumberOfIDs > 0) { 
      theWhere.Append("("); 

      foreach (int i in this.Domains.ListOfIDs) { 
       if (this.Domains.ListOfIDs.IndexOf(i) > 0) { 
        theWhere.Append(string.Format(" {0} ", this.Domains.AndOr == AndOrEnum.And ? "&&" : "||")); 
       } 
       theWhere.Append(string.Format("Domains.Any(IdDomaine== {0})", i)); 
      } 
      theWhere.Append(")"); 
     } 

     return theWhere.ToString(); 
    } 

即產生類似: 「(DispoJours.Any(IdDispo == 3)& & DispoJours.Any(IdDispo == 5))」。

我所有的其他「建設者」將做與「& &」相同的事情,它們之間給出正確的結果。

及更高版本:

var queryWithWhere = from c in m_context.Candidats.Where(WHERE) 
        select c; 

WHOOOHOOO!謝謝你們。非常有用!喜歡這個網站!


更新

不要忘了,我使用動態的LINQ在此查詢。這不是一個正常的LINQ查詢。

+2

如果您打算使用字符串構建實際查詢,請確保參數化字符串,否則您可能容易受到SQL注入攻擊。雖然它可能是更簡單的方法,但有時它不一定是最好/最安全的方式。如果您使用LINQ進行查詢,它會自動爲您查詢查詢。 – MunkiPhD 2009-08-20 17:23:34

+0

非常感謝,以防止我。現在我們不再使用SQL了,我忘記了那些危險的事情。謝謝。但在我的情況下,用戶不寫「1」,他在複選框列表中選擇它,所以危險並不在那裏。無論如何,我會這樣做,但不是真的是危險。 – 2009-08-20 17:39:19