LinQ Join with Multiple Conditions in On Clause WITH LAMBDA SYNTAX - linq

I have seen several SO posts explaining how to write a LinQ Join with an additional join condition on top of the key equality.
For instance this one :
LINQ Join with Multiple Conditions in On Clause
Is it possible to write this in lambda syntax? If so how?

Related

Spring JPA paginated query with Join Fetch - Count Query gives fetch error

(Note: all code examples are extremely simple. I know there are other ways to do such simple queries. The problem I am demonstrating, however, is a bigger deal for more complex queries).
There is a known issue with Spring JPA Repositories and paginated queries that I'm really hoping there is a good solution for. In JPQL, it is possible to use JOIN FETCH to specify that I want to eagerly fetch a related entity, rather than doing it lazily. This avoids the N+1 problem, among other things. JOIN FETCH requires that the owner of the association is included in the select clause. Here is a very simple example of the type of query I'm talking about:
#Query("""
SELECT p
FROM Person p
JOIN FETCH p.address
""")
Page<Person> getPeopleAndAddresses(Pageable page);
The problem with this kind of query is the pagination piece. When returning a Page, Spring will do the query I wrote but then also do a count query to get the total possible records. Spring appears to take my query exactly as written, and just replace SELECT p with SELECT COUNT(p). Doing this means that the owner of the JOIN FETCH association is no longer present in the SELECT clause, which then results in the JPQL giving an error.
The only way I know how to resolve this is to construct the query with separate query and countQuery values, like this:
#Query(query = """
SELECT p
FROM Person p
JOIN FETCH p.address
""", countQuery = """
SELECT COUNT(p)
FROM Person p
""")
Page<Person> getPeopleAndAddresses(Pageable page);
This resolves the JPQL JOIN FETCH error, because the count query no longer contains a JOIN FETCH clause. However, for complex queries with sophisticated JOINs and WHERE clauses, this will lead to excessive code duplication as I will have to write all that logic in two places.
This seems like the kind of issue where there really should be a better solution available. I'm exploring various alternatives, including Specifications (mixed feelings), Blaze Persistence, and others. However, I'm wondering if there is some way in Spring itself to resolve this issue so that the first code example would work without an error?

how to write hql with in clauses

I need to write an hql query like :
select * from User aliasUser where ? in aliasUser.roles
All examples of IN clause I'm finding use collection as parameters, how can I write this query? Obviously doesn't work as it stands right now, I've tried already.

"the method join is not supported" with Tridion OData service & Linq

I'm trying to a join CustomMeta & PageContents to select a specific page via some metadata that has been set, but I'm getting a "the method join is not supported" error. I think the issue is with my linq statement, as the error happens before anything gets sent to the OData service. But what is the issue exactly? The linq statement looks fine to me:
var pages2 = (from p in cds.PageContents
join m in cds.CustomMetas on p.PageId equals m.ItemId
where m.ItemType==64 && m.KeyName=="SomeKey" && m.StringValue=="SomeValue"
select p).ToList<SDLODataClient.SDLOData.PageContent>();
UPDATE 1
This Tridion OData article has an example of a join but some of the MS Linq to OData articles I'm reading seem to suggest that joins aren't supported in Linq to OData (here)
To my knowledge, LINQ queries against Data Services (OData) does not support several methods. The one you are using is join is also falls under the same category hence you are seeing the error even though the syntax is very valid from LINQ point of view. join falls under "Projection and filtering operators" which is not supported query with LINQ against OData .
Here is the link that explains all the unsupported methods (Refer section - Unsupported LINQ Methods)
http://msdn.microsoft.com/en-us/library/ee622463(v=vs.100).aspx
Back to your question, I am not quite how to achieve what you are looking for but I would try the following (you might have to get the results in multiple iterations):
Get the list of Page IDs that match the custom meta query (sample snippet - not tested)
_client.CustomMetas.Where (
m => m.KeyName == "somekey" && m.StringValue == "somevalue" && m.ItemType == 64)
.ToList();
Now you could query Page Contents using the above page ids. You might have build the filter type query for each page id.
Hope this helps.
Have you tried using the concept of expand ?
In OData service we do not have the join query but there is Expand keyword, wherein two entities (tables) that have a foreign key relationship can be used together to get a result set. It works as follows:
from item in table1.Expand(table2).AsEnumerable()
where (item.property1.Equals("x") & item.table2[0].prop2.Equals("y"))
select item
Here the second entity is exposed as an property of the first entity.

LINQ Lambda Order in writing the query

I have the following query:
var query = db.Prog
.Where (a => a.Prog != "00000" && a.fn != "Koll")
.Select(a => new {a.Prog, a.MEfn})
.OrderByDescending(a => a.MEfn)
The query works fine but wondering if there are general rules on the order in which you write a Lambda linq query. Meaning, .Where comes before .Select, etc.
Can somebody enlighten me on the order in which LINQ needs to be written or best practices.
There isn't a best practice on the order in which you write a LINQ query, it will depend on if you want to do your filtering first, or your projection. For example in your case, you are projecting to an anonymous type which doesn't include the 'fn' property which your filter uses, so it wouldn't be available to use in a where clause if your select was first.
A better practice would be to give your properties less cryptic names. Also, 'fn' doesn't follow the PascalCase for property names, and if it's a field then it probably shouldn't be public.
Yours can be a good order.
Let's distinguish the case where db points to an SQL DB with a very good LINQ provider and the case db is an in-memory object. I guess it's the first.
In case you are using a LINQ to SQL provider, the statements are evaluated only when you materialize the query into an object, so the SQL optimizer (inside the DB) will take care of ordering of statements.
The vice versa occurs when your statements are run against in-memory collections or to materialized collections coming from LINQ to SQL. In that case they are executed sequentially, so you want to execute first those statements that reduce the number of results in the collection. Where is the best candidate!!!
The order that they should be in are completely dependent on the context of what you are doing. So if your OrderBy is simply formatting the data to be friendly to view, put it at the end after you have trimmed your collection, if your looking for the First value of a sorted collection then maybe you would need it before the collection is iterated to get the first.

Linq to ... and Lambda Expressions

I have a big question that has been puzzling me for a long time and that I can't seem to get a straight answer for anywhere and I am sure that if someone can answer this with authority and with good examples that it will help not only me but thousands of developers to come. All I want to know is what are the characteristics of the following concepts and what are the differences between them
Linq
Linq to SQL
Linq to Entities
Linq to Objects
Lambda expressions
Also, in particular, can someone tell us where constructs such as these fall into the above categories
Construct 1
var result = from n in nums
where n < 5
orderby n
select n;
Construct 2
Entities.Person.Where(p => p.FirstName == "John").First();
Your learned clarifications are eagerly awaited.
I'm sure there are some over-simplifications here, but for what it's worth:
Linq is an API designed for dealing with data sets. IQueryable, for instance, comes from the System.Linq namespace. Linq to ... are different implementations that parse the same Linq instructions to perform different operations based on how your data is stored. So Linq to SQL will parse your .Where instruction to produce a sql query with a WHERE clause, while Linq to Objects would take that same instruction and produce a foreach.
A lambda expression is pretty much a shorthand for an anonymous delegate. You identify a lambda by the => operator. Your argument list is at the left hand of the => and the expression that can access those arguments and optionally return a result is at the right hand.
Your two code examples are different syntaxes in which Linq queries can be written. They are called Query syntax and Method syntax, respectively.

Resources