When to use JOIN and when not to in LINQ to entities - linq

I am new to Linq and I have seen that if there are multiple entities, some use the multiple FROM syntax like this:
from h in db.Hubs
from ch in h.CityHubs where ch.Cities.CityID == 1
select
and some use the explicity join syntax.
from h in db.Hubs
join ch in da.CityHubs on h.CityId equals ch.CityId
select
If I am using Linq to entities, which one should I use? If I were to use Linq to objects, which one should I use?

As a rule, in Entity Framework, if you have a proper model and properly set up navigation properties for foreign keys, you should almost never use join - instead you access your navigational property directly and EF will generate the necessary join in the SQL code for you. I recommend taking a look at #Craig Stuntz's blogpost regarding this issue.
Regarding Linq-to-objects, however, it depends on the particular query you are writing.

Related

Run complex SQL Query with spring boot repositories

i have a little complex scenario using spring data and jpa currently.
My data structure is like:
And i like to create a filter: give me all events which belongs to a list of structures, within a given period and is assigned to a list of categories.
I was able to create a sample SQL statement:
select * from event e inner join period p on e.period_id=p.id
inner join category_item_ids ci on e.id=ci.item_ids
inner join category c on ci.category_id=c.id
inner join event_assignment_structure_ids es on es.event_assignment_id=e.id
where p.start between '2020-05-01 12:00:00.000000' and '2020-11-14 12:00:00.000000' and
c.id in (1) and
es.structure_ids in (1,2)
But my objects are currently not wired together by all the JPA annotations.
e.g. the "Same ID" is something i did by convention to make the parts a little more independend.
So using the JPA way is currently no option i guess due to the missing relations.
Introducing them will be also quite a lot of work.
So i was wondering if there is a possiblity to run the sql query directly (i could use native query, but thats also no option, cause the filter values are not always given, so i need 13 native queries)
I used enityManager and query Builder in the past, but thats also no option due to the missing jpa relations.
Any ideas are much welcome :-)
Regards
Oliver

How to navigate many-to-many relationships in entity framework core

According to Microsoft Docs
https://learn.microsoft.com/en-us/ef/core/modeling/relationships#other-relationship-patterns
Many-to-many relationships without an entity class to represent the
join table are not yet supported.
Ok, this leads to a nightmare when you need to migrate apps with several many-to-many relationships that were handled perfectly by EF5.
Now I have Keyword, Tag and KeywordTag entities set up as described in the link.
If I have a keyword entity, which is the correct syntax to retrieve all tags associated with such keyword?
In EF5 it was
var kwd = _context.Keywords.Find(my_kwd_id);
var tagList = kwd.Tags;
Which is the equivalent with EF Core?
Intellisense allows me to write
kwd.KeywordTags
but not
kwd.KeywordTags.Tags
...so I cannot find how to access Tags in any way...
Please don't tell me that i have to explicitly search then loop the KeywordTag entity to extract Tags ...
Since EF Core does not have exact parity with older versions of EF, you need to write bit different code. You would need to do what #Ivan suggested in comments. You also need to eager load your collection because lazy loading is not available. That means you need to do database query explicitly.
Method 1: Instead of using Find you query database directly and bring in related data. (kwd/tagList) would have same data as you are seeing in EF5.
var kwd = db.Keywords.Include(k => k.KeywordTags)
.ThenInclude(kt => kt.Tag)
.FirstOrDefault(k => k.Id == my_kwd_id);
var tagList = kwd.KeywordTags.Select(kt => kt.Tag).ToList();
Alternatively, you can use find but load navigations explicitly. This is somewhat similar to lazy loading but since it is not available you ask EF to load navigations. This will have really bad perf as you will send 1 query to fetch all entries from join table & then 1 query for each related tag in tags table. If you are interested in knowing the way to write it, I can post code for that too.
Tags is an IEnumerable<Tag>. You can iterate over Tags with a foreach loop.

Using referencing class field as filter in Spring Data Repository

Context: I have three models, Owner, Property and Community. Property has a reference to its Owner, and another one to the Community.
I need to make the following query: find all the owners in a community which meet some criteria (floor number, property letter, etc, all the fields of the criteria are inside the Property class)
Is there any way to implement this in a repository without creating a bidirectional relationship or writing a native query? Something like:
Set<Owners> findAllByCommunityAndProperty_floorNumberAndProperty_letter(Community community, Property property);
(I would need a bidirectional relationship to make the query above)
You can use a query like this
SELECT o
FROM Property p
INNER JOIN property.owners o
WHERE p. ...
See http://www.objectdb.com/java/jpa/query/jpql/from#INNER_JOIN_ for various examples of join syntax.
In Spring Data JPA you will probably use the #Query annotation to bind that query to a method.

Left Join 1 to 1/0 with llblgen?

With EF, if you navigate to a singular related entity within a select projection(such as from the many side of a many-to-one or 1-to-1/0) it would coalesce nulls and give you a left join: https://stackoverflow.com/a/2525950/84206
Since it occurs in a project and not in a join, EF makes a pretty reasonable assumption that a left join is desired.
However, I haven't found a way to accomplish this in LINQ with LLBLGen. The above technique produces an inner join with LLBGen. I can't use techniques that use DefaultIfEmpty because that's only available when navigating into a many relationship.
I am hoping to avoid using WithPath/Prefetch because I'd really like to do the projection in LINQ instead of grabbing a huge object graph into memory and do the projection in memory.
This is LLBLGen 3.5.
If the FK is nullable, the join will be a left join. If the FK isn't nullable, it will be an inner join. This is the only way it's determinable what you want as Linq lacks any other system to specify the join type in this. Your link must use a nullable (optional) FK side as well to get a left join.
If nothing helps, please use queryspec, the query api will allow you to specify the join type in any case.
ps: please next time post on our forums, we don't monitor SO every day, but we do monitor our forums.

LINQ to CRM - OR in Where clause

I am trying to bring some data from Dynamics CRM 2011 using LINQ. The goal is to bring all Contact records that have changes since certain date OR have a child entity (PERC files) changed since that same date. The query looks like that:
// Bring all students who have changes (at Contact entity) after specific date
// momentInTime or the status of any of their perc files has been changed since
// that date
var students = (from c in ContactSet
join pl in cga_portallogonSet on c.Id equals pl.cga_ContactId.Id
join ef in cga_percfileSet on c.Id equals ef.cga_StudentId.Id
where
(pl.cga_PortalLogonRole.Value == 284970000) // student
where
(c.ModifiedOn >= momentInTime || c.CreatedOn > momentInTime)
||
(ef.cga_statuschangedate >= momentInTime)
select c.cga_StudentNumber).Distinct().ToList();
This produces the following error message:
'Contact' entity doesn't contain attribute with Name = 'cga_statuschangedate'.
I cannot figure out how to do OR on two different entities. The MSDN says you need WHERE clause for each entity:
where Clause
In order to filter the result set, where clauses can be added against one or more of the >entities. Each where clause may only contain conditions against an individual entity type. >A composite condition involving multiple entities is not valid. Instead, each entity >should be filtered in separate where clauses.
http://msdn.microsoft.com/en-us/library/ff681565.aspx
Is there another way of achieving what I need?
Unfortunately you cannot achieve what you want in a single linq statement beacuse the liunq provider they use boils down to fetchXML, and fetchXML does not support the scenario you are using.
More detail... Fetch gives you condition's inside of entity's or link-entity's. These condition elements cannot have attributes in them from other linked entities, only the direct parent entity or link-entity. Here is one of many microsoft forum posts referencing this limitation of fetchXML
Probably not the answer you were looking for, eh? As an ugly alternative you you can run two separate queries and filter in memory (as damaging as that may be to performance). Or better yet if you are an on-premise deployment you can write some sql against the filtered views. Good luck.

Resources