Sergej Popov
Sergej Popov

Reputation: 3021

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.

Upvotes: 3

Views: 1835

Answers (1)

Feng Zhao
Feng Zhao

Reputation: 2995

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);    
    }

Upvotes: 2

Related Questions