Code Review Stack Exchange is a question and answer site for peer programmer code reviews. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

In onion arch. we have multi layer structre:

UI (User interface). BL (Business Logic / Services). RE (Repositories).

UI uses BL to get data from RE with some conditions, my question is which is better approach (as standard) to get data from BL:

In Repository (Data Access Layer):

public class PersonRepository
{
   PersonEFDbContext context = new PersonEFDbContext();
   public IEnumerable<Person> GetPerson(Expression<Func<Person,bool>> Where)
   {
      return context.PersonsList.Where(Where).ToList();
   }
}

Entity:

public class Person
{
   [Key]
   public int Id { get; set; }
   public int NationalityId { get; set; }
}

case 1:

public class PersonProvider
{
    private PersonRepository repository { get; set; }
    public IEnumerable<Person> GetPersonListByNationality(int NationalityId)
    {
       return repository.GetPerson(p => p.NationalityId == NationalityId);
    }
}

then I have to use it in UI like this way:

public class PersonListViewModel
{
   IEnumerable<Person> PersonsList { get; set; }
   public PersonListViewModel(PersonProvider Provider, int NationalityId)
   {
      PersonsList = Provider.GetPersonListByNationality(NationalityId);
   }       
}

case 2:

public class PersonProvider
{
    private PersonRepository repository { get; set; }
    public IEnumerable<Person> GetPersonList(Expression<Func<Person,bool>> Where)
    {
       return repository.GetPerson(Where);
    }
}

then I have to use it in UI like this way:

public class PersonListViewModel
{
   IEnumerable<Person> PersonsList { get; set; }
   public PersonListViewModel(PersonProvider Provider, int NationalityId)
   {
      PersonsList = Provider.GetPersonList(p=>p.NationalityId == NationalityId);
   }       
}

So where is the right place to set conditions, which one is better for later maintenance ?

share|improve this question
public class PersonRepository
{
    PersonEFDbContext context = new PersonEFDbContext();
    public IEnumerable<Person> GetPerson(Expression<Func<Person,bool>> Where)
    {
       return context.PersonsList.Where(Where).ToList();
    }
}  

Let us first talk about this little code snipet.

Usually I would say that it is always best to code against interfaces so returning an IEnumerable<T> would be the way to go but because we are dealing with database access a consumer of this method would assume hey, it is an IEnumerable<T> so if I access this there will be several trips to the db. The consumer doesn't know that you had called ToList() before you returned it so the consumer will just call ToList() on the result so he is on the safe side.

This additional call to ToList() doesn't come at no cost. It involves some null checks, casts, initialization of objects, and some copy work.

I would like to suggest to return an IList<Person> instead which makes it clear for the caller that it is a list.

If we now look at the method I like to mention 2 points.

  • based on the NET naming guidelines method parameters should be named using camelCase casing, so Where should be where.

  • a method parameter named Where isn't well named. A much better name would be e.g filterExpression or filterCondition.

That beeing said, let me answer (although it is my personal opinion) you question about which of the version is better/should be used.

There are two sides

  • if you use the second approach you are limiting any caller to use NET 3.5 and higher.

  • if you use the first approach you are limiting the caller in the meaning of flexibility.

Personally I would go with the second approach because of the increased flexibility it will bring in the game.

Small nitpicking aside from the mentioned points:

Let your variables and operators some space to breathe. Here

public class PersonListViewModel
{
   IEnumerable<Person> PersonsList { get; set; }
   public PersonListViewModel(PersonProvider Provider, int NationalityId)
   {
      PersonsList = Provider.GetPersonList(p=>p.NationalityId == NationalityId);
   }       
}  

this would be more readable if you add a space after p and after => like so

public class PersonListViewModel
{
   IEnumerable<Person> PersonsList { get; set; }
   public PersonListViewModel(PersonProvider Provider, int NationalityId)
   {
      PersonsList = Provider.GetPersonList(p => p.NationalityId == NationalityId);
   }       
}
share|improve this answer
    
Flexibility is good everywhere, and I agree to have it, my point is the list which comes from business logic should not be different, so we don't have to allow any body to change the conditions, and to use different conditions in many places. thanks for the other remarks. – Mahmoud Hboubati Oct 7 '15 at 8:48
    
What exactly about the second approach limits it to 3.5+? – RubberDuck Oct 7 '15 at 9:13
1  
@RubberDuck Expression had first been introduce in NET 3.5 – Heslacher Oct 7 '15 at 9:16

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.