I'm developing an application with NHibernate 3.0. I have developed a Repository hat accept a expression to do some filter with QueryOver. My method is something like this:
public IEnumerable<T> FindAll(Expression<Func<T, bool>> filter) {
return Session.QueryOver<T>().Where(filter).List();
}
It works fine. So, I have a Service layer as well, and My methods in this services accepts primitives types, like this:
public IEnumerable<Product> GetProducts(string name, int? stock, int? reserved) {
// how init the expression ?
Expression<Func<Product, bool>> expression = ???;
if (!string.IsNullOrEmpty(name)) {
//add AND condition for name field in expression
}
if (stock.HasValue) {
//add AND condition for stock field in expression
}
if (reserved.HasValue) {
//add AND condition for reserved field in expression
}
return _repository.FindAll(expression);
}
My doubts are:
Is it possible ? Ta add some conditions when necessary (when my parameters has value) ?
Thanks
/// my edits
public ActionResult Index(ProductFilter filter) {
if (!string.IsNullOrEmpty(filter.Name) {
return View(_service.GetProductsByName(filter.Name))
}
// others conditions
}
/// Almost a solution
Expression<Func<Product, bool>> filter = x => true;
if (!string.IsNullOrEmpty(name))
filter = x => filter.Compile().Invoke(x) && x.Name == name;
if (stock.HasValue)
filter = x => filter.Compile().Invoke(x) && x.Stock == stock.Value;
if (reserved.HasValue)
filter = x => filter.Compile().Invoke(x) && x.Reserved == reserved.Value;
return _repository.FindAll(filter);
Your repository method definition suggests that you see FindAll as something that you pass criteria in and get a completed result back. Why not instead just have the result be of type IQueryable and return Session.QueryOver?
Your service layer would then do something like this, chaining together the "wheres":
So here is how you could actually and lambdas together - it borrows most of it's code from this awesome answer from desco that deserves an up-vote.
}
Then calling the code is quite simple ....
...
Here is a way to do this. I am not going to editorialize on what you are doing - it looks like query by example, which is almost always problematic. It is as the others here have best avoided. The expression thing is interesting though - so I thought it was worth a crack at it.
And we want to query it like this:
So all you have to do is write
RemoveCloture();
- not a problem.}
First, I'd solve your problem by avoiding it in the first place. I'd have different methods for this.
These all have trivially easy implementations in terms of a lambda expression. For example:
etc.
Second, yes what you want to do is possible but it's not the way I'd solve the problem.