vcRobe
vcRobe

Reputation: 1781

Retrieving a subset of rows from an OData endpoint

I've an ASP.NET Web API 2 exposing an OData endpoint.

In the front-end I'm using ASP.NET MVC 5. To consume the endpoint I'm using a WCF Services References.

The problem I'm facing is that I need to retrieve a subset of rows from the endpoint given the list of IDs.

Here's the entity I'm using in the OData endpoint

class MyEntity
{
  public int ID {get; set;}
  public string Name {get; set;}
  public int Age {get; set;}
}

Using LINQ I've solved this in other situations using the following statement

var result = entitiesContext.MyEntity
  .Where(x => idsEmployees.Select(y => y).Contains(x.ID));

where idsEmployees is the lists of IDs of the employees I need to retrieve.

Using this statement in the current scenario I get the following exception:

Error translating Linq expression to URI: The method 'Contains' is not supported.

How can I solve this?

Thank you.

Upvotes: 1

Views: 441

Answers (1)

vcRobe
vcRobe

Reputation: 1781

After some digging I found a solution in this blog

https://blogs.msdn.microsoft.com/phaniraj/2008/07/16/set-based-operations-in-ado-net-data-services/

Here's an extension method that solve the problem

/// <summary>
/// Retrieves the subset of entities in a table exposed through OData
/// </summary>
/// <typeparam name="T">Entity type</typeparam>
/// <typeparam name="U">Subset type</typeparam>
/// <param name="query"></param>
/// <param name="Set"></param>
/// <param name="propertyExpression"></param>
/// <returns></returns>
public static DataServiceQuery<T> SubSet<T, U>(
    this DataServiceQuery<T> query, 
    IEnumerable<U> Set, 
    Expression<Func<T, U>> propertyExpression)
{
    //The Filter Predicate that contains the Filter criteria
    Expression filterPredicate = null;
    //The parameter expression containing the Entity Type
    var param = propertyExpression.Parameters.Single();
    //Get Key Property 
    //The Left Hand Side of the Filter Expression
    var left = propertyExpression.Body;
    //Build a Dynamic Linq Query for finding an entity whose ID is in the list
    foreach (var id in Set)
    {
        //Build a comparision expression which equats the Id of the Entity with this value in the IDs list
        // ex : e.Id == 1
        Expression comparison = Expression.Equal(left, Expression.Constant(id));
        //Add this to the complete Filter Expression
        // e.Id == 1 or e.Id == 3
        filterPredicate = (filterPredicate == null) 
            ? comparison 
            : Expression.Or(filterPredicate, comparison);
    }

    //Convert the Filter Expression into a Lambda expression of type Func<Lists,bool>
    // which means that this lambda expression takes an instance of type EntityType and returns a Bool
    var filterLambdaExpression = 
        Expression.Lambda<Func<T, bool>>(filterPredicate, param);
    return (DataServiceQuery<T>)query.Where<T>(filterLambdaExpression);
}

and here's the way to use it

var result = entitiesContext.MyEntity.Subset<MyEntity, int>(idsEmployees, x => x.ID);

Upvotes: 1

Related Questions