Convert regular SQL to LINQ to Entities - c#

After a lot of search, I cannot find a simple answer to this following SQL Statement :
SELECT t1.LoginName, t0.BNAME
FROM USR02 AS t0
LEFT OUTER JOIN LoginData AS t1
INNER JOIN Mandants AS t2 ON t1.Id_Mandants = t2.Id_Mandants
ON t0.BNAME = t1.LoginName AND t0.MANDT = t2.CodeMandant
Because of the double ON statement I don't know how to write it in LINQ.
I've tried to simplify it but multiple primary key make the job hard.

Start by translating the SQL query to one that is more natural. Like this:
SELECT t1.LoginName, t0.BNAME
FROM USR02 AS t0
LEFT OUTER JOIN LoginData AS t1
ON t0.BNAME = t1.LoginName
INNER JOIN Mandants AS t2
ON t1.Id_Mandants = t2.Id_Mandants
WHERE t0.MANDT = t2.CodeMandant
Now it should be easy to translate this to LINQ. When you have you have set up the relationships in your entity model correctly, you would be able to write the following LINQ query:
from data in db.LoginData
where data.User.MANDT == data.Mandant.CodeMandant
select new { data.LoginName, data.User.BNAME };
btw. Why are you outputting both LoginData.LoginName as USR02.BNAME since they are always equal?

You need to convert your query to regular, 1-level join:
select t1.LoginName, t0.BNAME
from USR02 as t0
left outer join LoginData as t1 on t0.BNAME = t1.LoginName
inner join Mandants as t2 on t0.MANDT = t2.CodeMandant and t1.Id_Mandants = t2.Id_Mandants
Then it will be much easier to rewrite it on LINQ to Entities:
from t0 in db.t0
join t1 in db.t1 on t0.BNAME equals t1.LoginName
join t2 in db.t2 on new { t0.MANDT, t1.Id_Mandants} equals new { t2.CodeMandant , t2.Id_Mandants }
select new { t1.LoginName, t0.BNAME };

I like writing joins in this way
from t0 in db.t0
from t1 in db.t1.Where(x => t0.BNAME == x.LoginName).DefaultIfEmpty()
from t2 in db.t2.Where(x => t0.MANDT == x.CodeMandant)
.Where(x => t1.Id_Mandants == x.Mandants)
select new { t1.LoginName, t0.BNAME };

Related

How to apply Right Outer Join using LINQ in C#?

I am facing issue to apply Right Outer Join in LINQ. I am trying to build the similar query in LINQ by converting from SQL query.
My correct SQL query
select *
from Table1 t1
inner join Table2 t2 on t1.Id = t2.FID and t1.CID = 20
right outer join Table3 t3 on t1.GID = t3.GID
var result = from t1 in Table1
join t2 in Table2
on t1.ID equals t2.FID into gr1
where t1.CID = 20
join t3 in Table3
on t1.GID equals t3.GID into gr2
from t3 in gr2.DefaultIfEmpty()
select new Details (){
}
return result.ToList();
}
My LINQ query is not working as expected to SQL query.
This is also discussed here
how to make a right join using LINQ to SQL & C#
var RightJoin = from adds in dc.EmpresaAddendas
join cats in CatAddendas
on adds.IDAddenda equals cats.IDAddenda into joined
from cats in joined.DefaultIfEmpty()
select new
{
Id = cats.IDAddenda,
Description = cats.Descripcion
};
Try this:
var result = from t1 in Table1
join t2 in Table2
on new { id = t1.ID; cid = t1.CID } equals new { id = t2.FID: cid = 20} into gr1
join t3 in Table3
on t1.GID equals t3.GID into gr2
from t123 in gr2.DefaultIfEmpty()
select new Details (){
}
return result.ToList();
}
As you're discovered, most LINQ providers don't offer support for a right join. DefaultIfEmpty translates into a LEFT join. As a result, you need to flip the logic of your query around a bit to turn the right join into a left one.
As far as the actual syntax, I've had success adopting more of an ANSI-82 syntax rather than worrying about the into temp2 from temp3 in temp2 syntax. Something along the lines of:
var result =
from t3 in Table3
from t1 in Table1.Where(temp1 => temp1.GID == t3.GID).DefaultIfEmpty()
join t2 in Table2 on t1ID equals t2.FID
where t1.CID == 20
select new Details{};

How to translate SQL to LINQ with individual field joins?

I have a SQL statement, that I want to implement in a .NET website project. I don't understand how to join in a particular field, as the fields aren't available when I just select from the table.
My SQL
SELECT *
FROM [vResidence] c
JOIN [vJobs] j on c.UID = j.UID
This is the LINQ I have tried, but I am stuck at the 'ON' part:
results = (from j in vJobs
join cr in vResidence on ??? )
When I try 'j.', the only option I get is 'equals'.
You can follow as this.connect to tables as JOIN use equals keyword
var result = from r in vResidence
join j vJobs on r.UID equals j.UID
select new {[yourcolnum]};
You can try this
var result = (from j in vJobs
join cr in vResidence
on j.UID equals cr.UID
select new {
...
}).ToList();
The Linq expression is the following:
from t1 in Table1
join t2 in Table2
on t1.ID equals t2.ID
The join clause on must be do in order: first the first table, then the second.
The keyword equals must be use.
Apart from the above Linq answers, we can do JOIN using Enumerable.Join extension with Lambda expressions. Try something like,
var result = vJobs.Join(vResidence, jb => new { jb.UID }, res => new { res.UID },
(jb, res) => new { jb, res })
.Select(x => x.jb) //Select the required properties (from both objects) with anonymous object or select left/right object
.ToList();
C# Fiddle with sample data.

c# I need to perform this SQL Select to LINQ

I have this Select:
SELECT (MyFields)
FROM table1 T1
INNER JOIN table2 t2 ON t2.ID_t2 = T1.ID_T1
INNER JOIN
table3 t3 on t3.ID_t3=T1.ID_T1 and Left(t3.Other_t3_field,5)=t2.Another_t2_field
WHERE (Conditions)
Then, I tried in C#:
var query = from T1 in table1
join t2 in table2 on T1.ID_T1 equals t2.ID_t2
join t3 in **table3** on T1.ID_T1 equals v.ID_t3
join t4 in **table3** on t2.Other_t2_field equals Microsoft.VisualBasic.Strings.Left(t2.Another_t3_field, 5)
where (Conditions)
select new
{
(My fields)
};
Both works, but my C# query have more results then SQL Select, I don't know what I am doing wrong?
Well I'd start by changing the join on table 3 in the C# - use an anonymous type to join on multiple fields:
join t3 in table3 on new { Id = t1.ID_T1, X = t2.AnotherT2Field.Substring(0, 5) }
equals new { Id = t3.ID_T3, X = t3.OtherT3Field.Substring(0, 5) }
(I'd hope you can use Substring instead of Left here... it's much more idiomatic C#.)
You can add multiple join conditions with an anonymous type:
var query = from T1 in table1
join t2 in table2 on T1.ID_T1 equals t2.ID_t2
join t3 in **table3** on new {
ID = T1.ID_T1,
substring = t2.Other_t2_field
} equals new
{
ID = v.ID_t3,
substring = Microsoft.VisualBasic.Strings.Left(t2.Another_t3_field, 5)
}
where (Conditions)
select new
{
(My fields)
};
As Jon Skeet mentioned: you can also use Substring instead of Left.

Linq to Entity Framework: Multiple left outer joins create full outer

I can't find a good example, probably I'm searching wrong:
I have a bunch of tables joined via expression syntax and I'd like to left outer join two more, if there are values, otherwise return NULL.
So the sql is looking like this:
select *
from table1 mr
left outer join table2 on table1
left outer join table3 on table2
left outer join table4 on table3
where mr.id = 1234
So a left join is no problem with the syntax like this:
join oiA in query1 on organisation.Id equals oiA.Organisationid into qOrgInhA
from oiA in qOrgInhA.DefaultIfEmpty()
But as soon as I add the other tables depending on the oiA, the Entity Framework produces a Cross-Join, and not a second left outer join.
From what I've read, GroupJoin might be the solution, but I really can't find a good example, the most examples I found have just 2 tables.
Or am I doing something totally wrong?
In method syntax, multiple left joins can be done like this:
var result = table1
.GroupJoin(table2, o => o.Key, i => i.FKey, (t1, t2) => new
{
t1,
t2.GroupJoin(table3, o => o.Key, i => i.FKey, (_t2, t3) => new
{
_t2,
t3
})
});
The resulting query produced by entity framework will be similar to:
select * from table1
left outer join table2 on table1.Key = table2.FKey
left outer join table3 on table2.Key = table3.FKey
Edit:
I'm a bit shaky on query syntax, but its the same idea of doing the second join within the select:
var result = from t1 in table1
join t2 in table2 on t1.Key equals t2.FKey into joinresult
select new
{
t1,
from jr in joinresult
join t3 in table3 on jr.Key eq t3.FKey into joinresult2
select new
{
jr,
joinresult2
}
}

LINQ2SQL - More Questions on when a Cross join with where clause is emitted instead of Inner Join

This is a two part question and for education purposes rather than trying to find a solution to a problem.
I've seen this already and realize that it's very similar to my question
LINQ2SQL - Cross join emitted when I want inner join
But I am hoping for more information from you LINQ and SQL gurus as to why the cross join is created instead of inner join in LINQ2SQL. Additionally, can someone explain how SQL Server decides on the execution plan (or link to further information) since both of these queries generate the same plan? From what I understand, this means that the performance of the queries are the same.
I've created a small example that runs two LINQ expressions on my database that generates these two different SQL queries.
For those who don't want to bother, here's my example db diagram:
http://dl.dropbox.com/u/13256/Screen%20shot%202011-03-16%20at%2011.41.56%20AM.png
Here are the two queries:
Cross Join with Where Clause
var q = from item in context.Items
join i_mem in context.Memberships on new { item_id = item.ID, user_id =
current_user_id.Value } equals new { item_id = i_mem.RelatedItemID, user_id =
i_mem.RelatedUserID } into sq_i_m
from im in sq_i_m.DefaultIfEmpty()
join i_cat in context.Categories on item.RelatedCategoryID equals i_cat.ID
into sq_i_cat
from proj in sq_i_cat
select item;
Inner Join
from item in context.Items
join i_mem in context.Memberships on
new { item_id = item.ID, user_id = current_user_id.Value }
equals
new { item_id = i_mem.RelatedItemID, user_id = i_mem.RelatedUserID }
into sq_i_m
from im in sq_i_m.DefaultIfEmpty()
join i_cat in context.Categories on item.RelatedCategoryID equals i_cat.ID
select item
And here is the test program if you'd like to see for yourself.
Thanks for everyone's help.
Mustafa
They are the same thing, so it does not matter which LINQ2SQL emits.
An inner join is logically equivalent to a cross join with a where clause filter equivalent to the on of the inner join clause.
That's why Sql Server generates the same query plan.
To be clear, the inner join:
Select f1
From T1 inner join T2 on T1.k = T2.k
where T1.f2 like 'X%'
Is the same as the cross join:
Select f1
From T1 cross join T2
where T1.k = T2.k
and T1.f2 like 'X%'
is the same as old-style SQL:
Select f1
From T1, T2
where T1.k = T2.k
and T1.f2 like 'X%'
Lets say you have a datacontext called MyDataContext.
using(MyDataContext db = new MyDataContext())
{
var q = db.Items.Where(x=> x.Categories.Name == "myCategory").Select(x=> x);
}
This is a very simple example, but you didn't need to write out a join or a subquery in TSQL syntax. (I hate writing TSQL).

Categories