【问题标题】:Composing Linq to Entity Query from multiple parameters从多个参数组合 Linq 到实体查询
【发布时间】:2009-10-12 13:42:46
【问题描述】:

我目前正在构建一个详细的搜索,我正在尝试弄清楚如何将我的 Linq 查询组合到我的实体中。

基本上我的用户可以在列表控件中选择 1* 项。 我无法理解的部分如下:

如何动态构建 Where AND( field is equal to this OR field is equal to this OR...) 子句 其中项目的数量是可变的。

数据库字段示例内容:'26、21、22、100、164、130'

示例:(想法是能够根据所选项目的数量生成此示例)

Offre.Where(o=> o.Domain.Contains("26") || o.Domain.Contains("100") )

Offre.Where(o=> o.Domain.Contains("26") )

Offre.Where(o=> o.Domain.Contains("26") || o.Domain.Contains("100") || o.Domain.Contains("22") )

然后我可以轻松地将生成的查询作为 IQueryable 并添加到该对象以构建我的查询。

有人可以为我的 AND (OR .. OR) 子句指出正确的方向吗?

【问题讨论】:

    标签: .net linq entity-framework


    【解决方案1】:
    【解决方案2】:

    To work around this restriction, you can manually construct an expression (Source)

    C#

    static Expression<Func<TElement, bool>> BuildContainsExpression<TElement, TValue>(
    
        Expression<Func<TElement, TValue>> valueSelector, IEnumerable<TValue> values)
    
    {
    
        if (null == valueSelector) { throw new ArgumentNullException("valueSelector"); }
    
        if (null == values) { throw new ArgumentNullException("values"); }
    
        ParameterExpression p = valueSelector.Parameters.Single();
    
        // p => valueSelector(p) == values[0] || valueSelector(p) == ...
    
        if (!values.Any())
    
        {
    
            return e => false;
    
        }
    
        var equals = values.Select(value => (Expression)Expression.Equal(valueSelector.Body, Expression.Constant(value, typeof(TValue))));
    
        var body = equals.Aggregate<Expression>((accumulate, equal) => Expression.Or(accumulate, equal));
    
        return Expression.Lambda<Func<TElement, bool>>(body, p);
    
    } 
    

    使用此实用方法,

    var query2 = context.Entities.Where(BuildContainsExpression<Entity, int>(e => e.ID, ids));
    

    VB.Net

    Public Shared Function BuildContainsExpression(Of TElement, TValue)( _
    ByVal valueSelector As Expression(Of Func(Of TElement, TValue)), _
    ByVal values As IEnumerable(Of TValue) _
       ) As Expression(Of Func(Of TElement, Boolean))
    
        ' validate arguments
        If IsNothing(valueSelector) Then Throw New ArgumentNullException("valueSelector")
        If IsNothing(values) Then Throw New ArgumentNullException("values")
    
        Dim p As ParameterExpression = valueSelector.Parameters.Single()
        If Not values.Any Then
            Return _
                Function(e) False
        End If
    
        Dim equals = values.Select( _
            Function(v) _
                Expression.Equal(valueSelector.Body, Expression.Constant(v, GetType(TValue))) _
        )
    
        Dim body = equals.Aggregate( _
            Function(accumulate, equal) _
                Expression.Or(accumulate, equal) _
        )
    
        Return Expression.Lambda(Of Func(Of TElement, Boolean))(body, p)
    End Function
    

    使用这个实用方法

       Dim query = m_data. Offer
    
       If (selectedSectors.Count > 0) Then
            query = query.Where(BuildContainsExpression(Function(o As Offer) o.Value, selectedSectors))
       End If
    

    【讨论】:

      【解决方案3】:

      如果您的Offre 有某种与之关联的唯一ID,您可以尝试以下方法:

      List<int> queryCriteria = new List<int>;
      
      //Fill your query criteria here
      
      //Instead of o.Domain.Id you can use whatever ID you have.
      var resultSet = Offre.Where(o => queryCriteria.Contains(o.Domain.Id));
      

      【讨论】:

      • 这在您执行 Linq to Objects 时很好,但我希望我的查询完全在 SQL Server 上执行。
      • 对不起,我的老板一直在调用对象实体,所以我一直把这两者混为一谈。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-27
      • 2015-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多