Search code examples
c#odatalazy-loadingasp.net-web-api2

Enable lazy loading on OData URL Query


It seems when returning IEnumerable from Web API Endpoint OData Query it enumerates \ does eager loading before applying query options. Here is what I mean:

SomeType:

public class SomeType
{
    public int SomeProp { get; set; }
}

Endpoint:

public class SomeTypeController : ApiController
{

    [EnableQuery]
    public IEnumerable<SomeType> Get()
    {

        return GetSomeTypes();

    }
    IEnumerable<SomeType> GetSomeTypes()
    {
        for (var i = 0; i < 10; i++)
        {

            Trace.WriteLine(i);

            yield return new SomeType { SomeProp = i };
        }
    }
}

when requesting /api/sometype?$top=2 I would expect to Trace 2 lines (0,1) but instead I see loop continuing to the end.

I expect behaviour same as calling Take(2) before returning:

Endpoint:

public class SomeTypeController : ApiController
{

    [EnableQuery]
    public IEnumerable<SomeType> Get()
    {

        return GetSomeTypes().Take(2);

    }
    IEnumerable<SomeType> GetSomeTypes()
    {
        for (var i = 0; i < 10; i++)
        {

            Trace.WriteLine(i);

            yield return new SomeType { SomeProp = i };
        }
    }
}

Is there any way to switch on Lazy loading for OData query options?

Query options is the only reason I use OData, so alternatives that can implement automatic query options are welcome.


Solution

  • The IEnumerable enumerates 10 times because default orderby is applied.

    This behavior is by design because $top requires a stable sort.

    If you don't want this, you can set the EnsureStableOrdering with false.

        [EnableQuery(EnsureStableOrdering = false)]
        public IEnumerable<SomeType> Get()
        {
            return GetSomeTypes().Take(2);    
        }