2013-04-01 116 views
1

我試圖構建一個動態泛型方法。創建高級搜索機制。使用LINQ構建動態查詢

我可以使用動態LINQ

IQueryable<Table> query = ObjectContext.Table; 
if (parameters != null && parameters.Count > 0) 
{ 
    foreach (KeyValuePair<string, dynamic> keyValuePair in parameters) 
    { 
     query = query.Where(keyValuePair.Key + " == @0", new object[] { keyValuePair.Value }); 
    } 
} 

但這樣做實現的東西,我需要加載每個字段像這樣的東西

ClassTable.Parameters.Add("FKTable.Foo", foo); 
ClassTable.Parameters.Add("Bar", bar); 

所以我用另一種方法(試圖此代碼有效)

List<Table> lstTable = new List<Table>(); 
lstTable.AddRange(tableDAO.SelectWhere(
    u => this.EntityValues.Foo == u.Foo && this.EntityValues.Bar == u.Bar 
)); 
return lstTable; 

現在,我的問題是,我想做一些更喜歡(此代碼只將第一次查詢的結果),我不想做這樣的事情

List<Table> lstTable = new List<Table>(); 
lstTable.AddRange(tableDAO.SelectWhere(
    u => !string.IsNullOrEmpty(this.EntityValues.Foo) ? this.EntityValues.Foo == u.Foo : false 
    && 
    this.EntityValues.Bar != 0 ? this.EntityValues.Bar == u.Bar : false 
)); 
return lstTable; 

IQueryable<Data.Story> query = ctx.DataContext.Stories; 

if (criteria.StoryId != null) // StoryId 
    query = query.Where(row => row.StoryId == criteria.StoryId); 

if (criteria.CustomerId != null) // CustomerId 
    query = query.Where(row => row.Project.CustomerId == criteria.CustomerId); 

if (criteria.SortBy != null) // SortBy 
    query = query.OrderBy(criteria.SortBy + " " + criteria.SortOrder.Value.ToStringForSql()); 

我知道我的問題有點混亂,我會提供編輯和評論來解決它。只是讓我知道。


TL; DR;我需要幫助來創建一個動態查詢,我只需要傳遞在搜索中使用的參數。所以我可以爲用戶創建一個高級搜索選項。

+1

這是你在找什麼? [動態LINQ](http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx)或者可能[ Predicate Builder](http://www.albahari.com/nutshell/predicatebuilder.aspx)? – jrummell

+0

@ jrummell是的,我正在閱讀這兩個主題,偉大的順便說一句。謝謝+1 –

回答

0

p.s.w.g suggested in his answer,我不得不這樣做我自己,但我確實從他的提議有點不同。

我在我的DAO類中創建了兩個方法。第一個,我加載一個表達式列表,並在第二個我讀它並執行。

public List<System.Linq.Expressions.Expression<Func<E, bool>>> whereList = new List<Expression<Func<E, bool>>>(); 
public List<E> ExecuteSelectFilter() 
{ 
    System.Linq.Expressions.Expression<Func<E, bool>> whereFinal = c => true; 

    foreach (System.Linq.Expressions.Expression<Func<E, bool>> whereItem in whereList) 
    { 
     if (whereItem != null) 
     { 
      var invokedExpr = Expression.Invoke(whereFinal, whereItem.Parameters.Cast<Expression>()); 

      whereFinal = Expression.Lambda<Func<E, bool>> 
        (Expression.AndAlso(whereItem.Body, invokedExpr), whereItem.Parameters); 
     } 
    } 
    return this.ObjectContext.CreateQuery<E>(EntitySetName).Where(whereFinal.Compile()).ToList(); 
} 

這些方法我在DAO電話,讓我可以從任何公務艙我有機會。

tableDAO.whereList.Clear(); 

#region Filters 
// Foo 
if (!String.IsNullOrEmpty(this.entityValues.Foo)) 
    tableDAO.whereList.Add(q => q.Foo.Contains(this.entityValues.Foo)); 
// Bar 
if (this.entityValues.Bar > 0) 
    tableDAO.whereList.Add(q => q.Bar== this.entityValues.Bar); 
#endregion 

return tableDAO.ExecuteSelectFilter(); 

希望這有助於某人,就像它幫助了我。

2

你可以自己編寫Expression的:

public static IQueryable<T> Where<T>(this IQueryable<T> source, string propertyOrFieldName, object value) 
{ 
    var param = Expression.Parameter(typeof(T), "x"); 
    var prop = Expression.Property(param, name); 
    var @const = Expression.Constant(value, prop.Type); 
    var equals = Expression.Equal(prop, @const); 
    var lambda = Expression.Lambda(equals, param); 
    return source.Where(lambda); 
} 

foreach(var p in parameters) 
{ 
    query = query.Where(p.Key, p.Value); 
} 
+0

我試過這個。沒有按我的意願= /但這是一個很好的答案。 +1 –