Search code examples
c#-4.0paginationnhibernatelinq-to-nhibernatenhibernate-3

Calling Fetch in NH 3.1 ignores Skip and Take


We have a query we're attempting to write for paging, where we want to use Fetch to eager load a collection for an object, then return a paged list of that object. The query below does not work because when we look in the profiler, it skips the Skip and Take settings, and just returns the list of objects (eagerly loaded):

var result = _repostitory.All<MediaFile>()
            .Skip(10)
            .Take(10)
            .Fetch(mf => mf.Tags);

Everything compiles and executes but, the skip and take parts are ignored and all the data is being brought back. Is it possible to use Fetch in conjunction with Skip and Take for paging?


Solution

  • Have you tried calling fetch before skip and take

    var result = _repostitory.All<MediaFile>()
    .Fetch(mf => mf.Tags)            
    .Skip(10)
    .Take(10);
    

    From what I remember NH cannot handle join eager loading with limits on the query (it has to do with SQL and not NH). It might work with sub select though.

    **UPDATE

    Consider this example

    TableA
    -------------
    Id|Value
    -------------
    1 |Value1
    2 |Value2
    3 |Value3
    
    TableB
    -------------------------
    ChildId|ParentId|ChildValue
    -------------------------
    1      |       1|Value1
    2      |       1|Value2
    3      |       2|Value3
    4      |       2|Value4
    5      |       3|Value5
    6      |       3|ValueA
    7      |       3|ValueA
    8      |       3|ValueA
    
    
    
    SELECT * FROM TableA LEFT JOIN TableB ON TableA.Id = TableB.ParentId
    
    Result
    --------------------------------------
    Id|Value |ChildId|ParentId|ChildValue
    --------------------------------------
    1 |Value1|1      |       1|Value1
    1 |Value1|2      |       1|Value2
    2 |Value1|3      |       2|Value3
    2 |Value1|4      |       2|Value4
    3 |Value1|5      |       3|Value5
    3 |Value1|6      |       3|ValueA
    3 |Value1|7      |       3|ValueA
    3 |Value1|8      |       3|ValueA
    
    
    SELECT TOP 2 * FROM TableA LEFT JOIN TableB ON TableA.Id = TableB.ParentId
    
    Result
    --------------------------------------
    Id|Value |ChildId|ParentId|ChildValue
    --------------------------------------
    1 |Value1|1      |       1|Value1
    1 |Value1|2      |       1|Value2
    

    Therefore the .Take(2) will return one object with two children (Id 1). Where you would want to return the first two objects (Id 1,2) with their children.