Here is a LINQ query:
from a in db.Table1
join b in db.Table2 on a.Id1 equals b.Id2
I am wondering the reason of equals keyword.
Why did the LINQ creators have to create this keyword? Couldn't they work with ==?
Is there a particular reason ?
As per Microsoft's docs:
A join clause performs an equijoin. In other words, you can only base matches on the equality of two keys. Other types of comparisons such as "greater than" or "not equals" are not supported. To make clear that all joins are equijoins, the join clause uses the equals keyword instead of the == operator.
That's the main reason. There are also some other difference between equals and == to make the operator better suitable for LINQ. One important difference is that the operator isn't symmetric. You have to write
join b in db.Table2 on a.Id1 equals b.Id2
Using
join b in db.Table2 on b.Id1 equals a.Id2
throws a compiler error.
Not mentioned (but implicated by the join being an equijoin): another difference is that the operator can't be chained. These join expressions are invalid:
join b in db.Table2 on a.Id equals b.Id || a.Id equals b.Id2
join b in db.Table2 on a.Id equals b.Id && a.Id2 equals b.Id2
The latter join can be coded by using a composite key.
I think it was a great decision to use a special contextual keyword. It makes developers pay attention and doesn't raise expectations that an == operator might have done.
Related
I have come across some hql that looks like this:
select a.id
from something a inner join a.whatever b,
somethingelse c inner join c.blah d
where a.id = c.id
Why is a inner joined to b and c inner joined to d but a is linked to c via where
What exactly is this hql saying? Please explain in simple terms.
This query means that the a and b are related in the model. Same is the case with c and d.
In order to join a and c, you have to explicitly state the join field, i.e., id since the model does not have this information.
So i have this:
SELECT p.plantnaam,o.levcode,o.offerteprijs
FROM plant p, offerte o
JOIN (SELECT plantcode , MIN(offerteprijs) AS offprijs
FROM offerte
GROUP BY plantcode) s
ON s.plantcode = p.plantcode
AND s.offprijs = o.offerteprijs
ORDER BY p.plantnaam,l.levcode
Appearently on the 6th row, p.plantcode is suddenly magically an invalid identifier. Why is this? and why are all the others from the exact same table perfectly fine before that point?
The problem is that you are mixing JOINs. You have both implicit and explicit joins. The explicit JOIN syntax with the ON clause has a higher precedence over the implicit join with the commas. As a result the alias for the plant and the offerte tables will not be available in the ON clause. Try using the same JOIN type throughout:
SELECT p.plantnaam, o.levcode, o.offerteprijs
FROM
(
SELECT plantcode , MIN(offerteprijs) AS offprijs
FROM offerte
GROUP BY plantcode
) s
INNER JOIN plant p
ON s.plantcode = p.plantcode
INNER JOIN offerte o
ON s.offprijs = o.offerteprijs
ORDER BY p.plantnaam, l.levcode
Is there any condition under which the two queries will yield different results?
select * from a,b,c where a.id = b.id(+) and a.id=c.id(+);
select * from a,b,c where a.id = b.id(+) or a.id=c.id(+);
I think in both cases, it will return the row if the id is in table a.
The second select fails with ORA-01719, Outer join operator (+) not allowed in operand of OR or IN.
Yet another reason to use ANSI JOIN syntax. You couldn't even conceive of this question if you were doing so.
Dim ds = From a In db.Model
Join b In db.1 On a.id Equals b.ID
Join c In db.2 On a.id Equals c.ID
Join d In db.3 On a.id Equals d.ID
Join f In db.4 On a.id Equals f.ID
Select a.id, a.Ref, a.Type, a.etc
Above is my linq query. At the moment I am only getting the first row from the db returned when there are currently 60 rows. Please can you tell me where I am going wrong and how to select all records.
Thanks in advance!
UPDATE:
When I take out all the joins like so:
Dim ds = From a In db.1, b In db.2, c In db.3, d In db.4, f In db.5
Select a.id, a.Ref, a.type, b.etc, c.etc, d.etc
I get a system.outofmemory exception!
You're only going to get a row produced when all of the joins match - in other words, when there's a row from Model with an AP, an Option, a Talk and an Invoice. My guess is that there's only one of those.
LINQ does an inner join by default. If you're looking for a left outer join (i.e. where a particular row may not have an Invoice, or a Talk etc) then you need to use a group join, usually in conjunction with DefaultIfEmpty.
I'm not particularly hot on VB syntax, but this article looks like it's what you're after.
This emits inner joins, which is what I want and works:
var q =
from itm in esdc.items
join itmImg in esdc.itemImages on itm.itemId equals itmImg.itemId
join itmIdent in esdc.itemIdentities on itm.imgIdentityId equals itmIdent.itemIdentityId
join startImgs in esdc.vStartPgImgs on itmImg.imgId equals startImgs.imgId
select ...
This works too, but cross joins were emitted. How do I get inner joins? I double checked the entities and the relationships are correct.
var q =
from itmIdent in esdc.itemIdentities
from itm in itmIdent.items
from itmImg in itm.itemImages
join startImgs in esdc.vStartPgImgs
on itmImg.imgId equals startImgs.imgId
select ...
If you need me to post the emitted SQL and the entity setup, let me know.
To put it simply: you get inner joins if you use the first form. Multiple from clauses represent cross joins (sort of, anyway 1) in LINQ.
Basically, if you want inner joins, use multiple join clauses.
1 (I say sort of because the subsequent sequences can depend on the earlier ones... but for LINQ to SQL they're almost always cross joins.)