2009-10-12 70 views
1

我目前正在建立一個詳細的搜索,我想弄清楚如何編寫我的Linq查詢到我的實體。從多個參數編寫Linq到實體查詢

基本上我有用戶可以在列表控件中選擇1 *項目。 我不能繞到我的頭部分如下:

我怎麼能動態地構建一個 AND(字段等於這個或現場等於這個或......)子句 其中項目數量是變體。

數據庫領域樣本內容:'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)子句指向正確的方向嗎?

回答

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 
0

如果您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)); 
+0

這是很好的,當你正在做Linq到對象,但我希望我的查詢完全在SQL Server上執行。 – 2009-10-12 16:47:32

+0

對不起,我的老闆一直在調用對象實體,所以我一直在混合這兩個實體。 – 2009-10-12 17:01:41