Linq OData "Where" clause on nested list - linq

Say I have the following query OData Linq Query (run against http://odata.netflix.com/v2/Catalog):
Genres.Where(x=>x.Name=="Adventures")
.Select(y=> new
{
Genre = y.Name,
Movie = y.Titles.Select(l=> new
{
l.Name,
l.AverageRating
})
})
How could I change this query to give me the rows where AverageRating was 3?
(NOTE: The point of this question is to find out how to do a where clause on properties of an expanded sub list of my main level query item. My real query is not even against the Netflix OData feed.)

The short answer is that it's not possible currently.
The $filter always (and only) applies to the top-level entity set. There's currently no way to filter expanded entity sets.
The $filter can reach inside the expanded entity sets but the result will always filter the top-level set. In V2 it works for singleton navigation properties (the expression in $filter can traverse those), in V3 you can use the any/all to also incorporate collection navigation properties.
The reason this can't work is that the OData protocol doesn't define the URI syntax for nested filters. In fact it doesn't define almost any operator on the expanded entity sets except for the expansion itself and projections.

Related

OData query to filter a collection based on a navigation property's expanded value

I have a quotes collection I'd like to filter through a navigation property value. This navigation property is not a collection, but rather the id to another discrete linked entity.
My use case is {{ crmApiBaseUrl }}/quotes?$expand=fs_NAVIntegrationMarkerId&$filter=fs_NAVIntegrationMarkerId/fs_name eq 'Open'
I want to see all of the quotes where the associated fs_NAVIntegrationMarkerId's fs_name property value is equal to 'Open'.
The above query returns "The Property (0) is not a primary key of the related entity".
Try
{{ crmApiBaseUrl }}/quotes?$expand=fs_NAVIntegrationMarkerId($filter=fs_name eq 'Open')
Checkout the Nested filter in expand from this documentation https://www.odata.org/getting-started/basic-tutorial/#filter
Take a look at the Microsoft Docs reference for options to apply to expanded tables. It has great examples of how to apply a filter to an expanded table that are specific to the Dynamics Web API.
{{crmApiBaseUrl}}/quotes?$expand=fs_NAVIntegrationMarkerId($filter=fs_name eq 'Open')

Using aliased expression used in select clause into my order by clause for a criteria query

I have a requirement which is somewhat similar to this. My API supports a filter where there is more than 8 filter parameter. So, I want to create a query dynamically based on the filter parameter passed. I am using CriteriaBuilder to create a dynamic query.
Now, I am able to create dynamic queries successfully but the issue comes when the user wants to sort on an aggregate functions. In my query, I have 4 aggregate (count) function. So to support sorting on these columns, I just use the expression of this aggregate function but what I want is to use the alias of this expression
Repeating the expression in select and order by doesn't seem right to me. So, is there a solution/workaround to the problem. I want to declare the expression alias once and use it in both select and order by clause and if required in my group by clause in future
You probably need to build a custom projection class, you can find a decent and easy one, SQLProjectionWithAliasSupport in https://hibernate.atlassian.net/browse/HHH-2952 (from Sergey Pulyaev)
If then one wants to support also sub criteria, things get more complicate

Linq to Sharepoint results in invalid cast

I am programming a Silverlight application in c#, which takes lists from a sharepoint.
I want the distinct elements from a specific column in the list.
After getting the query I can't handle with the var-datatype. The program exists everytime, when I want to make a datacast, for example in an ListItemCollection.
Here is the code:
ListItemCollection bla;
var result = bla.Select(m => m["Region"]).Distinct();
ListItemCollection a = (ListItemCollection)result; //Error happens here
LINQ deals with instances of IEnumerable<> or IQueryable<>. Distinct returns an IEnumerable<> or IQueryable<> depending on the type of the original collection. In your case, it returns an IQueryable
You are trying to cast that IQueryable to a ListItemCollection, which understandably results in an invalid cast exception.
You don't need to do something else to start working with the items. You can iterate over them with foreach, convert them to an array or list with ToArray() and ToList() etc
Linq provider for SharePoint does not support Distinct operator which is why this error occurs.
According to MSDN:
Some LINQ queries cannot be completely translated into CAML. However,
however such queries can, in principle, run correctly because they can
be executed in two stages. First, the LINQ to SharePoint provider
translates as much of the query into CAML as it can and executes that
query
Please refer Unsupported LINQ Queries and Two-stage Queries for a more details.
Two stage approach
To correct this error, you should cut your queries in two stages to force the first query execution before the second one. To do that, you should for example transform the first IEnumerable<T> in a list thanks to ToList() method.
The following example demonstrates how to return unique values from ListItemCollection object:
var result = items.ToList().Select(i => i["Region"].ToString()).Distinct(); //System.Linq.Enumerable.DistinctIterator<string> type
foreach (var item in result)
{
//...
}

How to use linq to entities queries or Lists in linq to sql queries

I have a generic EF repository and need to get items from database using nested where statements.
var categoryGroups = repository.Categories.Where(a => a.Vehicles.Where(v =>
bodyTypesFilter.Any(b => b == v.BodyType)).Count() > 0);
I include only the important part of lambda expression.
Here bodyTypesFilter is a List and I'm getting following exception.
Unable to create a null constant value of type 'System.Collections.Generic.List`1'. Only entity types, enumeration types or primitive types are supported in this context.
I understand that it's due to I'm trying to generate linq to sql query which includes List and it isn't allowed. But I don't know how to avoid it or overcome.
Please help to find out a solution.
It's about the part
bodyTypesFilter.Any(b => b == v.BodyType)
You can't compare objects in EF queries, because the part bodyTypesFilter can't be translated into SQL. Do this in stead:
bodyTypesFilterIds.Contains(v.BodyType.Id)
(or probably v.BodyTypeId)
where bodyTypesFilterIds is a list of Id values in stead of objects.
(Not Any, because that creates a monster query that easily develops into a too deep nesting level).

Linq, what is difference in returning data in var, list, IEnumerable and IQueryable?

I am new to Linq please guide me on some basic things.
In read some articles on Linq. Some authers fill data in var from Linq query, some fills list of custom type objects and some fills data in IEnumerable and some do it in IQuryable. I could not get what is difference in these 4 and which one should be used in which situation.
I want to use Linq to SQL. What should I use?
Well, you can never declare that a method returns var - it's only valid for local variables. It basically means "compiler, please infer the static type of this variable based on the expression on the right hand side of the assignment operator".
Usually a LINQ to Objects query will return an IEnumerable<T> if it's returning a sequence of some kind, or just a single instance for things like First().
A LINQ to SQL or EF query will use IQueryable<T> if they want further query options to be able to build on the existing query, with the added bits being analyzed as part of the SQL building process. Alternatively, using IEnumerable<T> means any further processing is carried out client-side.
Rather than focusing on what return type to use, I suggest you read up on the core concepts of LINQ (and the language enhancements themselves, like var) - that way you'll get a better feel for why these options exist, and what their different use cases are.

Resources