This question already has answers here:
C# Null coalesce with LINQ
(4 answers)
Closed 4 years ago.
This is my SQL query:
select
S.student_No,
coalesce(P.Name,'0'),
P.Surname
from
Person as P
join
Student as S
on P.Id = S.Person_Id
I want to convert it LINQ , i did it except coalesce function,
from P in cbu.PERSON
join S in cbu.STUDENT on P.ID equals S.PERSON_ID
select new
{
S.Stundent_No,
P.Name,
P.Surname,
};
how can I use coalesce in this linq query
P.Name ?? "0". C# has the coalesce operator built-in. Even if you didn't know that, you could use the ?: operator.
The join is not necessary, btw. You can just write P.Student.Stundent_No (or whatever the properties are called).
Related
This question already has answers here:
Linq to Entity Join table with multiple OR conditions
(3 answers)
LEFT OUTER JOIN in LINQ
(24 answers)
Closed 6 months ago.
I have the following SQL query that has left join with tow parameters
select val1,val2 from tbl1
left join tbl2 on (tbl1.ID = tbl2.ForKey1 or tbl1.id= tbl2.ForKey2)
What is the equivalent Linq query to it that retrieve the same result ?
You can use documented Collection selector references outer in a non-where case
var query =
from tbl1 in ctx.tbl1
from tbl2 in ctx.tbl2
.Where(tb2 => tbl1.ID == tbl2.ForKey1 || tbl1.id == tbl2.ForKey2)
.DefaultIfEmpty()
select new
{
tbl1,
tbl2
};
This question already has answers here:
Why use a JOIN clause versus a WHERE condition?
(11 answers)
Closed 7 years ago.
I'm little question... I think this is only a semantic question...
Can anyone explain me real diff on these two query? If there is one...
// #1 - Query with join
SELECT DISTINCT cli.COD_CLIENTE
FROM CLIENTI cli
JOIN BANCHE b
ON b.COD_BANCA = cli.COD_BANCA
JOIN SOA_CONO_VISIB cv
ON cv.COD_SOCIETA = b.SOCIETA_SOA
AND cv.FLAG_ENTITA_OPER = 1
AND cv.COD_MACRO_CLASSE <> 'RFE'
AND cv.DATA_FINE_OPERATIVITA IS NULL
WHERE cv.COD_SOCIETA = '01'
AND cv.COD_ENTITA = '00008';
// #2 - Query with implicit join
SELECT DISTINCT cli.COD_CLIENTE
FROM CLIENTI cli, BANCHE b, SOA_CONO_VISIB cv
WHERE cv.COD_SOCIETA = '01'
AND cv.COD_ENTITA = '00008'
AND b.COD_BANCA = cli.COD_BANCA
AND cv.COD_SOCIETA = b.SOCIETA_SOA
AND cv.FLAG_ENTITA_OPER = 1
AND cv.COD_MACRO_CLASSE <> 'RFE'
AND cv.DATA_FINE_OPERATIVITA IS NULL;
They are exactly the same, with implicit join you have to "manually" do references between tables and, with query that select from many tables, this could be an excessive work.
Here another question like yours, maybe you could find other information.
http://www.stackoverflow.com/questions/44917/explicit-vs-implicit-sql-joins
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!
I have two classes: Property and PropertyValue. A property has several values where each value is a new revision.
When retrieving a set of properties I want to include the latest revision of the value for each property.
in T-SQL this can very efficiently be done like this:
SELECT
p.Id,
pv1.StringValue,
pv1.Revision
FROM dbo.PropertyValues pv1
LEFT JOIN dbo.PropertyValues pv2 ON pv1.Property_Id = pv2.Property_Id AND pv1.Revision < pv2.Revision
JOIN dbo.Properties p ON p.Id = pv1.Property_Id
WHERE pv2.Id IS NULL
ORDER BY p.Id
The "magic" in this query is to join on the lesser than condition and look for rows without a result forced by the LEFT JOIN.
How can I accomplish something similar using LINQ to EF?
The best thing I could come up with was:
from pv in context.PropertyValues
group pv by pv.Property into g
select g.OrderByDescending(p => p.Revision).FirstOrDefault()
It does produce the correct result but is about 10 times slower than the other.
Maybe this can help. Where db is the database context:
(
from pv1 in db.PropertyValues
from pv2 in db.PropertyValues.Where(a=>a.Property_Id==pv1.Property_Id && pv1.Revision<pv2.Revision).DefaultIfEmpty()
join p in db.Properties
on pv1.Property_Id equals p.Id
where pv2.Id==null
orderby p.Id
select new
{
p.Id,
pv1.StringValue,
pv1.Revision
}
);
Next to optimizing a query in Linq To Entities, you also have to be aware of the work it takes for the Entity Framework to translate your query to SQL and then map the results back to your objects.
Comparing a Linq To Entities query directly to a SQL query will always result in lower performance because the Entity Framework does a lot more work for you.
So it's also important to look at optimizing the steps the Entity Framework takes.
Things that could help:
Precompile your query
Pre-generate views
Decide for yourself when to open the database connection
Disable tracking (if appropriate)
Here you can find some documentation with performance strategies.
if you want to use multiple conditions (less than expression) in join you can do this like
from pv1 in db.PropertyValues
join pv2 in db.PropertyValues on new{pv1.Property_ID, Condition = pv1.Revision < pv2.Revision} equals new {pv2.Property_ID , Condition = true} into temp
from t in temp.DefaultIfEmpty()
join p in db.Properties
on pv1.Property_Id equals p.Id
where t.Id==null
orderby p.Id
select new
{
p.Id,
pv1.StringValue,
pv1.Revision
}
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.