Search code examples
c#mvvmrepository-patterniqueryablespecification-pattern

mvvm repository filtering


I have some master-detail classes based in large part on Josh Smith's msdn article. Its great code, especially for an example, but leaves me wondering how best to handle situations where you want some subset of a repository.

So Josh has a class called AllCustomersViewModel, and code something like:

    public AllCustomersViewModel(CustomerRepository customerRepository)
    {
        if (customerRepository == null) throw new ArgumentNullException("customerRepository");

        // Populate the AllCustomers collection with CustomerViewModels.
         _allCustomers = _customerRepository
            .GetCustomers()
            .Select(cust => new CustomerViewModel(cust, _customerRepository))
            .ToList();
   }

How do you solve a situation where you want PreferredCustomers, ExCustomers, LocalCustomers, etc, etc??

His code suggests to me a ViewModel class for each, with the filtering of the repository hard-coded in that class.

Or else a way to pass an optional filter into the ViewModel along with the repository?

How does your code solve this particular problem?

As an aside, does anyone have links or good examples showing how to use SpeciaficationPattern or IQueryable to solve issues like this?

Cheers,
Berryl


Solution

  • One option (and probably the cleanest) is to simply add those methods to the CustomerRepository - e.g. GetPreferredCustomers(), GetLocalCustomers() etc.

    Also, you should really be working against abstractions, so should pass an ICustomerRepository to your view model constructor. This decouples your view model code from your concrete customer repository (in this case one that reads from an XML file), and makes it easy to swap out implementations, e.g. for unit testing.

    The other option, as you mention, is for your repository to expose IQueryable<T>. If you are happy to be tied into IQueryable, and are confident that any data access implementation is going to support a LINQ provider, then that provides good flexibility. See here for more info.

    Personally, I prefer the first option, particularly for larger scale applications.