Alex Rivera | Logout

Should the UI layer be able to pass lambda expressions into the service layer instead of calling a specific method?

Asked 2012-01-24T15:12:30.120
10

The ASP.NET project I am working on has 3 layers; UI, BLL, and DAL. I wanted to know if it was acceptable for the UI to pass a lambda expression to the BLL, or if the UI should pass parameters and the Service method should use those parameters to construct the lambda expression? Here is an example class showing both senarios.

public class JobService 
{
    IRepository<Job> _repository;

    public JobService(IRepository<Job> repository) 
    {
        _repository = repository;
    }

    public Job GetJob(int jobID)
    {
        return _repository.Get(x => x.JobID == jobID).FirstOrDefault();
    }

    public IEnumerable<Job> Get(Expression<Func<Job, bool>> predicate)
    {
        return _repository.Get(predicate);
    }
}

For the above class is it acceptable for the UI to call the following:

JobService jobService = new JobService(new Repository<Job>());
Job job = jobService.Get(x => x.JobID == 1).FirstOrDefault();

or should it only be allowed to call GetJob(int jobID)?

This is a simple example, and my question is in general, should the UI layer be able to pass lambda expressions into the service layer instead of calling a specific method?

Edit
Report

1 Answer

4

This is always a moot point as to which 'layer' that exposing Expression trees (and IQueryables) should be limited to.

So first the obvious - the main benefit of allowing an IQueryable lambda into a layer obviously allows for enormous flexibility in the query, without the need for writing lots of GetXXXByYYY type methods. Client layers can also directly control the joins by using .Include to specify the depth of graph retrieval, and can control ordering (.OrderBy), grouping (.GroupBy), row limits (.Take) in the database, which generally will have performance gains over doing the same thing in memory.

The downsides include:

  • Testability - because the interface is so open, there are an arbitrarily large number of permutations to check.
  • Trust - clients of your layer have free reign to execute arbitrary queries against your database, which could have performance issues (i.e. clients could execute queries which miss all the Indexes) and security issues (retrieving data to which they should not have access).
  • Serialization - Expression Trees can't be directly serialized, so you couldn't expose your BLL across e.g. WCF (although they can be proxied)

If you do allow the Expression tree as a parameter, then I would suggest you go 'all the way' and return IQueryable instead of IEnumerable. This will allow the queries to be chained / aggregated (e.g. you can amend the query later on, before materialising it)

Personally we don't permit expression trees past our BLL, so we wouldn't extend this to our UI - IMO Expression<> predicates are seen as mechanism of implementing Evan's specification pattern.

answered 2012-01-24T15:27:37.703

Your Answer