6

我有一个项目要求我做一个这么大的搜索引擎,但它都是动态的。我的意思是我可以有大约 0 到 9 个主要的“组”,它们内部有无限的可能性,比如用“OR”或“AND”来“在哪里”。我们首先想到的是使用 Dynamic Linq,它为构建动态查询提供了一个很好的替代方案。所有这些都使用带有自制包装器的 EF。

问题:我无法访问“收藏”。我的意思是,我可以轻松访问引用的对象(如Customer.State.StateName = "New-York" OR Custoemr.State.StateName = "Quebec"),但我找不到访问类似的方法:" Customer.Orders.OrderID = 2 或 Customer.Orders.OrderID = 3"。我可以很容易地弄清楚这是因为它是一个集合,但我该怎么做呢?

请帮帮我!!

** 对不起我的英语不好 !!


更新

我不清楚我认为,对不起,因为我是法国人......

我的问题是因为没有什么是静态的。它是招聘公司的候选人搜索引擎,可将候选人放入企业。在经理可以搜索候选人的页面中,他可以通过以下方式“解析”:域(工作)、城市或许多其他用户在注册时填写的内容。所有这些都是格式(如果它是在 SQL 中):

[...] WHERE(domaine.domainID = 3 或 domaine.domainID = 5 或 domaine.domainID = 23)和(cities.cityID = 4,citys.city = 32)[...]

所以我不能用普通的 LINQ 格式来做到这一点,比如:

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

即使是括号中的运算符也是动态的(“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 个“可能”添加的东西要搜索......有什么想法吗?

4

5 回答 5

5

您需要在这里做的是构建一个LambdaExpression(更具体地说是一个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);

IE,

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

如果您需要手动执行此操作,则可读性不强。

在 MSDN 代码库的DynamicQuery下,有一个完全可操作的表达式解析器示例,它将根据Visual Studio 2008 的 C# 示例中的字符串实际为您执行此操作。(该控件在内部使用了此示例的略微修改版本。)LinqDataSource

于 2009-08-20T14:50:56.687 回答
4

最后,我完全按照我想要的方式得到了它。

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))”。

我所有的其他“Where builder”都将使用“&&”来做同样的事情,它们之间会给出正确的结果。

然后 :

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

呜呜呜!!谢谢各位。非常有用!喜欢这个网站!


更新

不要忘记我在这个查询中使用了 Dynamic Linq。这不是一个普通的 LINQ 查询。

于 2009-08-20T15:31:14.890 回答
1

假设 Customer.Orders 返回一个集合,这正是您不能只调用它的属性的原因。

为了使用 LINQ 获取您要查找的订单,您需要知道 OrderID(或其他一些属性),在这种情况下您可以执行以下操作:

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

编辑:要以这种方式添加表达式以查找 id 2 或 3:

Customer.Orders.FindAll(order => order.OrderID == 2 || order.OrderID == 3);
于 2009-08-20T13:12:52.033 回答
1

我是否理解正确,Customers 都是一个集合,Orders 是一个集合,而 State(显然)是一个 Property?

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) 

(从我的代码复制)。

于 2009-08-20T13:13:37.587 回答
0

如果您退后一步,询问客户想要做什么。

Filter bug information.

为什么不将数据导出到 excel 或将 excel 指向 SQL 表。构建起来没有那么有趣,但你会在几个小时内完成,而不是几天或几周。:)

于 2009-08-20T13:26:34.870 回答