I was trying to build a dynamic generic method. To create a advanced search mechanism.
I could achieve something using Dynamic 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 });
}
}
But doing this, I need to load each field with something like this
ClassTable.Parameters.Add("FKTable.Foo", foo);
ClassTable.Parameters.Add("Bar", bar);
So I'm trying with other approach (This code works)
List<Table> lstTable = new List<Table>();
lstTable.AddRange(tableDAO.SelectWhere(
u => this.EntityValues.Foo == u.Foo && this.EntityValues.Bar == u.Bar
));
return lstTable;
Now, my problem is, I wanted to do something more like (This code brings the result of the first query only)
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;
I didn't want to do something like this
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());
I know that my question is kinda jumbled, I'll provide edits and comments to fix it. just let me know.
TL;DR; I need help to create a dynamic query, where I only need to pass the parameters that are used in the search. So I can create a advanced search option to the user.
You could write the Expression
's yourself:
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);
}
Like pswg suggested in his answer , I had to do it myself, but I did a little different from what he suggested.
I create two methods in my DAO class. The first one, I load a List of expressions, and in the second I read it and execute.
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();
}
Those methods I call in my DAO, so I can access from any business class I have.
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();
hope this help someone, like it helped me.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.