Domain.Contracts.Specifications - Querying with filtering, sorting, pagination

Jan 16, 2010 at 12:13 AM
Edited Jan 16, 2010 at 12:27 AM

Hi All,

I'm looking a bit deeper at the querying part of the sample app, and have a few questions:

 

1) What's the role of Domain.Contracts.Specifications.ISpecification<T>? What is its relation to Domain.Contracts.Specifications.ILinqSpecification<T>?

 

2) Using ILinqRepository<T> and ILinqSpecification<T>, what is your approach to querying with pagination and sorting?

 

Thanks as always for all your feedback and help.

Best regards, Martin

Jan 16, 2010 at 12:27 AM

2) Using ILinqRepository<T> and ILinqSpecification<T>, what is your approach to querying with pagination?

 

One clean approach I have seen is to define a basic utility entity in the Domain like so:

 

public class PagedList<T>
{
    public ICollection<T> Page { 
        // intenal collection 
    }

    public int TotalResults { get; private set; }
    public int CurrentPageNumber { get; private set; }
    public int TotalPages { get; private set }
}

and then your base repository class implemented a method something like this:

 

public interface ILinqRepository<T>
{
    // ... existing stuff

    PagedList<T> FindAllPage(ILinqSpecification<T> specification, int pageNumber, int pageSize)

}

This approach is taken by KiGG (http://kigg.codeplex.com/), as well as Kona (http://mvcsamples.codeplex.com/).

 

Some reservations I have with this method are:

* Instead of the repo knowing about PagedList<T>, perhaps this should be the responsibility of the ApplicationService (aka WCHM Tasks) layer instead

* Technically, pageNumber and pageSize could also be ILinqSpecification instances, but I don't know how pretty that is

* The last querying pillar - sorting - is not accommodated in this solution

Developer
Jan 16, 2010 at 10:46 AM
Hi Martin,

On my current project, I've put pagination and ordering logic in the tasks layer. It looks a bit like this:

        public IPagination<Site> GetAll(int pageNumber)
        {
            return this.siteRepository.FindAll().OrderBy(s => s.SiteName).AsPagination(pageNumber);
        }

AsPagination is an extension method defined in MvcContrib.Pagination and it returns an IPagination which has the relevent properties for current page, total pages, total records, etc.

I've checked this out with the profiler, and under the covers NHibernate does some whizzy stuff so that only to correct page of results is pulled from the database.

Prior to using the MvcContrib stuff, I used Skip() and Take() which had the same effect, but you then also need to use Count() and do the maths to work out the rest of the detail you normally need.

If you dig into it, you'll see that there are two IPagination<T> implementations, a LazyPagination (which gets used in the case of the above) and a CustomPagination. In my controller layer, the mapper handles converting from IPagination<Site> to IPagination<SiteSummaryViewModel> by instantiating a CustomPagination<SiteSummaryViewModel> and populating it. This has the effect of forcing the database query to execute at that point. If you weren't using view models then obviously this is irrelevent.

What do you think of that approach?

Cheers
Jon



2010/1/16 martin_aatmaa <notifications@codeplex.com>

From: martin_aatmaa


2) Using ILinqRepository<T> and ILinqSpecification<T>, what is your approach to querying with pagination?

 

One clean approach I have seen is to define a basic utility entity in the Domain like so:

 

public class PagedList<T>
{
    public ICollection<T> Page { 
        // intenal collection 
    }

    public int TotalResults { get; private set; }
    public int CurrentPageNumber { get; private set; }
    public int TotalPages { get; private set }
}

and then your base repository class implemented a method something like this:

 

public interface ILinqRepository<T>
{
    // ... existing stuff

    PagedList<T> FindAllPage(ILinqSpecification<T> specification, int pageNumber, int pageSize)

}

This approach is taken by KiGG (http://kigg.codeplex.com/), as well as Kona (http://mvcsamples.codeplex.com/).

 

Some reservations I have with this method are:

* Instead of the repo knowing about PagedList<T>, perhaps this should be the responsibility of the ApplicationService (aka WCHM Tasks) layer instead

* Technically, pageNumber and pageSize could also be ILinqSpecification instances, but I don't know how pretty that is

* The last querying pillar - sorting - is not accommodated in this solution

Read the full discussion online.

To add a post to this discussion, reply to this email (whocanhelpme@discussions.codeplex.com)

To start a new discussion for this project, email whocanhelpme@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com


Developer
Jan 16, 2010 at 10:49 AM
Oh, I probably should have mentioned - the reason I still wanted to have an IPagination passed into the view is that MvcContrib also provides an HtmlHelper method called Pager that accepts an IPagination as input and renders out a paging control for you. So my PageViewModel has a property called Results, of type IPagination<SiteSummaryViewModel>, and I can do this in the view:

!{Html.Pager(Model.Results)}

Which is nice and quick.

Cheers
Jon

2010/1/16 Jonathan George <jon@jonathangeorge.co.uk>
Hi Martin,

On my current project, I've put pagination and ordering logic in the tasks layer. It looks a bit like this:

        public IPagination<Site> GetAll(int pageNumber)
        {
            return this.siteRepository.FindAll().OrderBy(s => s.SiteName).AsPagination(pageNumber);
        }

AsPagination is an extension method defined in MvcContrib.Pagination and it returns an IPagination which has the relevent properties for current page, total pages, total records, etc.

I've checked this out with the profiler, and under the covers NHibernate does some whizzy stuff so that only to correct page of results is pulled from the database.

Prior to using the MvcContrib stuff, I used Skip() and Take() which had the same effect, but you then also need to use Count() and do the maths to work out the rest of the detail you normally need.

If you dig into it, you'll see that there are two IPagination<T> implementations, a LazyPagination (which gets used in the case of the above) and a CustomPagination. In my controller layer, the mapper handles converting from IPagination<Site> to IPagination<SiteSummaryViewModel> by instantiating a CustomPagination<SiteSummaryViewModel> and populating it. This has the effect of forcing the database query to execute at that point. If you weren't using view models then obviously this is irrelevent.

What do you think of that approach?

Cheers
Jon



2010/1/16 martin_aatmaa <notifications@codeplex.com>

From: martin_aatmaa


2) Using ILinqRepository<T> and ILinqSpecification<T>, what is your approach to querying with pagination?

 

One clean approach I have seen is to define a basic utility entity in the Domain like so:

 

public class PagedList<T>
{
    public ICollection<T> Page { 
        // intenal collection 
    }

    public int TotalResults { get; private set; }
    public int CurrentPageNumber { get; private set; }
    public int TotalPages { get; private set }
}

and then your base repository class implemented a method something like this:

 

public interface ILinqRepository<T>
{
    // ... existing stuff

    PagedList<T> FindAllPage(ILinqSpecification<T> specification, int pageNumber, int pageSize)

}

This approach is taken by KiGG (http://kigg.codeplex.com/), as well as Kona (http://mvcsamples.codeplex.com/).

 

Some reservations I have with this method are:

* Instead of the repo knowing about PagedList<T>, perhaps this should be the responsibility of the ApplicationService (aka WCHM Tasks) layer instead

* Technically, pageNumber and pageSize could also be ILinqSpecification instances, but I don't know how pretty that is

* The last querying pillar - sorting - is not accommodated in this solution

Read the full discussion online.

To add a post to this discussion, reply to this email (whocanhelpme@discussions.codeplex.com)

To start a new discussion for this project, email whocanhelpme@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com



Jan 25, 2010 at 10:45 AM
martin_aatmaa wrote:

1) What's the role of Domain.Contracts.Specifications.ISpecification<T>? What is its relation to Domain.Contracts.Specifications.ILinqSpecification<T>?

In the interest of clarity, I have re-posted this question into a separate discussion thread:

More on ISpecification and ILinqSpecification

http://whocanhelpme.codeplex.com/Thread/View.aspx?ThreadId=81909