Reputation: 9666
I am using EF and want to pass WCF Service a filter function. Everything is ok if I have one filter, but when I try to combine some expressions together I get an anoying error: The underlying connection was closed: A connection that was expected to be kept alive was closed by the server.
So here is my Filter object:
public class EventFilter
{
public int CategoryId { get; set; }
public int SubCategoryId { get; set; }
public DateTime StartDate { get; set; }
public int? Duration { get; set; }
public string Address { get; set; }
}
And here is the filter function which works fine (one filter):
public IQueryable<Event> GetBySearch(EventFilter search)
{
Expression<Func<Event, bool>> where = null;
if (search.CategoryId != 0)
{
where = x => x.CategoryId == search.CategoryId;
}
return this.Context.Events.Where(where);
}
But if I want to expand it for two filters, it's not working and I can't understand how to fix it.
So, this is the combine function, which I believe is ok.
private static Expression<Func<TEntity, bool>> Combine<TEntity>(Expression<Func<TEntity, bool>> a, Expression<Func<TEntity, bool>> b)
{
var and = Expression.AndAlso(a.Body, b.Body);
var param = Expression.Parameter(typeof(TEntity));
return Expression.Lambda<Func<TEntity, bool>>(and, param); ;
}
And here is the problem filter function (it's not working when the both filters happens:
public IQueryable<Event> GetBySearch(EventFilter search)
{
Expression<Func<Event, bool>> where = null;
if (search.CategoryId != 0)
{
where = x => x.CategoryId == search.CategoryId;
}
if (search.SubCategoryId != 0)
{
where = Combine<Event>(where, x => x.SubCategoryId == search.SubCategoryId);;
}
return this.Context.Events.Where(where);
}
I have tried many various of writing it, I have tried to enter a new object to the result, for example:
public IQueryable<Event> GetBySearch(EventFilter search)
{
Expression<Func<Event, bool>> where = null;
Expression<Func<Event, bool>> where2 = null;
if (search.CategoryId != 0)
{
where = x => x.CategoryId == search.CategoryId;
}
if (search.SubCategoryId != 0)
{
where2 = x => x.SubCategoryId == search.SubCategoryId;
}
var result = Combine(where, where2);
return this.Context.Events.Where(result);
}
After all I payed attention that this code works:
Expression<Func<Event, bool>> where3 = (x => x.CategoryId == search.CategoryId) && (x => x.SubCategoryId == search.SubCategoryId);
While this is not:
Expression<Func<Event, bool>> where3 = where && where2; //Compile time error.
Maybe here the problems starts, can someone help me? Thanks !!!
Upvotes: 1
Views: 104
Reputation: 127563
Because multiple Where
clauses are AND
ed together and each clause returns a IQueryable<Event>
you can just chain multiple clauses together like this.
public IQueryable<Event> GetBySearch(EventFilter search)
{
IQueryable<Event> events = this.Context.Events; //(I assume Events is an IQueryable<Event>)
if (search.CategoryId != 0)
{
events = events.Where(x => x.CategoryId == search.CategoryId);
}
if (search.SubCategoryId != 0)
{
events = events.Where(x => x.SubCategoryId == search.SubCategoryId);
}
return events;
}
This effectively does (assuming both id's where not 0)
this.Context.Events.Where(x => x.CategoryId == search.CategoryId).Where(x => x.SubCategoryId == search.SubCategoryId);
which is the same as
this.Context.Events.Where(x => x.CategoryId == search.CategoryId && x.SubCategoryId == search.SubCategoryId);
Upvotes: 2