Difference between the LINQ join and sub from - linq

Is there any difference between these two LINQ statements:
var query = from a in entities.A
where a.Name == "Something"
from b in entities.B
where a.Id == b.Id
select b;
var query = from a in entities.A
join b in entities.B on a.Id equals b.Id
where a.Name == "Something"
select b;
Are both statements doing an inner join?
Also how do I view generated the generated SQL statement from the Entity Framework?

This doesn't precisely answer your question, but it's nearly always wrong to use join in LINQ to Entities. Both queries are, in my opinion, incorrect. What you actually want to do in this case is:
var query = from a in entities.A
where a.Name == "Something"
from b in a.Bs // where Bs is the name of the relationship to B on A,
select b; // whatever it's called
You already have the specification of the relationship encoded in your DB foreign keys and your entity model. Don't duplicate it in your queries.

You can get, and compare the SQL for, those queries:
((ObjectQuery)query).ToTraceString();
The generated SQL may be (subtly) different depending on how EF interprets those queries.
FYI- You don't have to include joins when querying related entities.

Logically speaking these two statements are doing the same thing. If they are computed differently by the framework then I would be unimpressed.

Take a look to the sql profiler. You could get your answer.

Related

Entity Framework "Joins" resulting in returning entire table from SQL

We are writing entity lambda expression query like this. But when we checked in profile. There were almost all the tables which were used in join returning entire table to the .net linq queries.
We have few transaction tables which has thousands of records. which is causing performance issue.
Please let us know if we can avoid table returning entire rows to .net
var result = (from f in f
join a in this.Context.a on f.primeryKey equals a.primeryKey
join d in this.Context.d on f.secondid equals d.secondid
join t in this.Context.t on d.thirdId equals t.thirdId
where t.isfoo && pfIds.Contains(a.fourthId.HasValue ? a.fourthId.Value : -1)
select f).Distinct().ToList();
Well, no real answer, for that I don't have enough info, but a few remarks to improve your query.
First remark: Don't do Contains and HasValue, because Linq won't SQL-ize these operations. I'm also not quite sure about the this.Context. stuff.
Second: NULL won't join in smart joins.
Third: Instead of selecting f, you'd typically select only a few fields of f that you need.
You'll need to rewrite your query. EF really needs to get all lines to utilize operator ? in order to evaluate value in a.fourthId column. I believe that
var result = (from f in f
join a in this.Context.a on f.primeryKey equals a.primeryKey
join d in this.Context.d on f.secondid equals d.secondid
join t in this.Context.t on d.thirdId equals t.thirdId
where t.isfoo && pfIds.Contains(a.fourthId)
select f).Distinct().ToList();
would meet your needs without necessary overhead, that evaluation seems to be superfluous.

Does place of Where clause matter in Linq query? [duplicate]

This question already has an answer here:
In explicit LINQ-to-SQL (C#) does order matter?
(1 answer)
Closed 8 years ago.
I have this linq Query in a C# project
var query = from p in db.Posts
join a in db.Author on p.Author equals a
join u in db.Users on p.PostedBy equals u
where p.IsActive.Equals(true)
orderby p.PostedDate descending
select new ViewModel
{
...
};
If I move where p.IsActive.Equals(true) near from p in db.Posts, like
var query = from p in db.Posts
where p.IsActive.Equals(true) //Moved
join a in db.Author on p.Author equals a
join u in db.Users on p.PostedBy equals u
orderby p.PostedDate descending
select new ViewModel
{
...
};
will it make any difference to the performance of the query?
I'm not sure that it will work if you'll do it, but if you are using it against a SQL database it should not make any difference. Both queries will be translated to the SQL like this one:
SELECT ...
FROM Posts INNER JOIN Author ON ... INNER JOIN Users ON ...
WHERE Posts.IsActive = true
...
Concerning performance, I would strongly suggest to put
the joins before any where.
The reason is, that the joins already make a smaller set
(the p is selected from Posts and then only
the matching rows from Author and Users are taken.
In opposite, if you have a where near the beginning
a caresian (big) product is calculated and then filtered.
(in your special case, only one table is affected, but
the query may be altered sometime and nobody knows then
why it is slow).
Please read this SO Why is LINQ join so much faster than LINQ where
And more on your special case: as this is affecting a database,
the resulting SQL statements should be the same in both queries.
Have a look at it!

Linq how to use Where on the result of Join

I need compute some join operations on my data, on the result of these operations I need to use a WHERE statement.
At the moment I use this syntax below, no errors, but result is not as expected.
For sure I need Group the result for my join and apply a query on it.
Could you please provide me an example of code? Unfortunately I'm pretty new at Linq and I'm not able to do it.
var myImagesForUser = from i in context.CmsImagesContents
join c in context.CmsContents on i.ContentId equals c.ContentId
join a in context.CmsAuthors on c.AuthorId equals a.AuthorId
join u in context.aspnet_Users on a.UserId equals u.UserId
where u.UserId == (Guid)myLoggedInUser.ProviderUserKey
select i;
Probably related data for current logged in user is not present in any one or more tables (Authors, Contents, ImagesContents) and you are not getting any result due to inner join on these tables. you can try outer join instead. Look at this article for left outer join in Linq queries
Hmm. I see two things which I would do different.
1.) You forgot to call .ToList() at the end in order to execute the query. Otherwise it can be, that you misuse the LINQ Statement in the processing afterwords.
var myImagesForUser = (YOUR LINQ STATEMENT).ToList();
2.) It's strange that you need to convert the UserKey to GUID. If really needed I would do it prior the LINQ Statement and check against a local variable.
var userId = (Guid)myLoggedInUser.ProviderUserKey;
var myImagesForUser = (YOUR LINQ STATEMENT ... where u.UserId == userId ).ToList();
Perhaps this helps you to get the expected result.
where a.UserId == (Guid)myLoggedInUser.ProviderUserKey.

Linq to entities Left Join

I want to achieve the following in Linq to Entities:
Get all Enquires that have no Application or the Application has a status != 4 (Completed)
select e.*
from Enquiry enq
left outer join Application app
on enq.enquiryid = app.enquiryid
where app.Status <> 4 or app.enquiryid is null
Has anyone done this before without using DefaultIfEmpty(), which is not supported by Linq to Entities?
I'm trying to add a filter to an IQueryable query like this:
IQueryable<Enquiry> query = Context.EnquirySet;
query = (from e in query
where e.Applications.DefaultIfEmpty()
.Where(app=>app.Status != 4).Count() >= 1
select e);
Thanks
Mark
In EF 4.0+, LEFT JOIN syntax is a little different and presents a crazy quirk:
var query = from c1 in db.Category
join c2 in db.Category on c1.CategoryID equals c2.ParentCategoryID
into ChildCategory
from cc in ChildCategory.DefaultIfEmpty()
select new CategoryObject
{
CategoryID = c1.CategoryID,
ChildName = cc.CategoryName
}
If you capture the execution of this query in SQL Server Profiler, you will see that it does indeed perform a LEFT OUTER JOIN. HOWEVER, if you have multiple LEFT JOIN ("Group Join") clauses in your Linq-to-Entity query, I have found that the self-join clause MAY actually execute as in INNER JOIN - EVEN IF THE ABOVE SYNTAX IS USED!
The resolution to that? As crazy and, according to MS, wrong as it sounds, I resolved this by changing the order of the join clauses. If the self-referencing LEFT JOIN clause was the 1st Linq Group Join, SQL Profiler reported an INNER JOIN. If the self-referencing LEFT JOIN clause was the LAST Linq Group Join, SQL Profiler reported an LEFT JOIN.
Do this:
IQueryable<Enquiry> query = Context.EnquirySet;
query = (from e in query
where (!e.Applications.Any())
|| e.Applications.Any(app => app.Status != 4)
select e);
I don't find LINQ's handling of the problem of what would be an "outer join" in SQL "goofy" at all. The key to understanding it is to think in terms of an object graph with nullable properties rather than a tabular result set.
Any() maps to EXISTS in SQL, so it's far more efficient than Count() in some cases.
Thanks guys for your help. I went for this option in the end but your solutions have helped broaden my knowledge.
IQueryable<Enquiry> query = Context.EnquirySet;
query = query.Except(from e in query
from a in e.Applications
where a.Status == 4
select e);
Because of Linq's goofy (read non-standard) way of handling outers, you have to use DefaultIfEmpty().
What you'll do is run your Linq-To-Entities query into two IEnumerables, then LEFT Join them using DefaultIfEmpty(). It may look something like:
IQueryable enq = Enquiry.Select();
IQueryable app = Application.Select();
var x = from e in enq
join a in app on e.enquiryid equals a.enquiryid
into ae
where e.Status != 4
from appEnq in ae.DefaultIfEmpty()
select e.*;
Just because you can't do it with Linq-To-Entities doesn't mean you can't do it with raw Linq.
(Note: before anyone downvotes me ... yes, I know there are more elegant ways to do this. I'm just trying to make it understandable. It's the concept that's important, right?)
Another thing to consider, if you directly reference any properties in your where clause from a left-joined group (using the into syntax) without checking for null, Entity Framework will still convert your LEFT JOIN into an INNER JOIN.
To avoid this, filter on the "from x in leftJoinedExtent" part of your query like so:
var y = from parent in thing
join child in subthing on parent.ID equals child.ParentID into childTemp
from childLJ in childTemp.Where(c => c.Visible == true).DefaultIfEmpty()
where parent.ID == 123
select new {
ParentID = parent.ID,
ChildID = childLJ.ID
};
ChildID in the anonymous type will be a nullable type and the query this generates will be a LEFT JOIN.

Is an outer join possible with Linq to Entity Framework

There are many examples of outer join using Linq to Sql, all of them hinging on DefaultIfEmpty() which is not supported with Linq to Entity Framework.
Does this mean that outer join is not possible with Linq to Entity using .NET 3.5 (I understand that DefaultIfEmpty is coming with 4.0 --- but that's not an option at this time for me)
Could somebody please provide a concise example using Linq to EntityFramework.
In LINQ to Entities, think in terms of relationships rather than SQL joins. Hence, the literal equivalent of a SQL outer join on an entity Person with a one to zero or one relationship to CustomerInfo would be:
var q = from p in Context.People
select new
{
Name = p.Name,
IsPreferredCustomer = (bool?)p.CustomerInfo.IsPreferredCustomer
};
L2E will coalesce the join, so that if CustomerInfo is null then the whole expression evaluates to null. Hence the cast to a nullable bool, because the inferred type of non-nullable bool couldn't hold that result.
For one-to-many, you generally want a hierarchy, rather than a flat, SQL-style result set:
var q = from o in Context.Orders
select new
{
OrderNo = o.OrderNo,
PartNumbers = from od in o.OrderDetails
select od.PartNumber
}
This is like a left join insofar as you still get orders with no details, but it's a graph like OO rather than a set like SQL.

Resources