Search code examples
c#linqodata

OData: Get Top-Level Collection by filtering second level navigation by list


I think the title explains it all but here is what I am trying to get from Simple.OData.Client;

public async Task<List<Party>> GetByGenres(List<Genre> Genres, params string[] expands)
    {
        IEnumerable<Party> rtn = null;

        try{
            rtn = await client.For<Party>("Party").Filter(p => p.Genres.Any(g => Genres.Contains(g))).FindEntriesAsync();
        }
        catch(Exception e){

        }
        return rtn.ToList();
    }

But it gives

Message "Not supported expression of type System.Linq.Expressions.TypedParameterExpression (Parameter): g" string

My model Genre ipmlements the IEquatable.

Any ideas? Regards.


Solution

  • We are so used to LINQ expressions that we sometimes forget that in case of external services there must be a LINQ provider capable of interpreting expressions that our applications send to it. An SQL database .NET driver is usually capable enough for such queries but even rich Microsoft SQL server and Oracle .NET drivers may fail on a complex LINQ expression that works fine on in-memory queries.

    Having said that, let's take a look at your expression that you send to OData Filter clause: p => p.Genres.Any(g => Genres.Contains(g)). You are sending a Genres list to the expression and want to check that at least one element in some collection is contained in Genres. While OData supports Any/All clauses, I am not sure the above expression can be written as a OData URI supported by OData V3 or V4 services. I might be wrong though but can you try to write an OData URI query that corresponds to your request, paste it in the browser and run agains your OData service? If so, then this is a Simple.OData.Client limitation that I can try to fix but I suspect this expression might be too complex for current OData protocol.