2009-08-20 69 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