Select In Select Statement - c#

What is an equivalent LINQ query to the following SQL query:
Select Id, Name
From Table1 tbl1
Where Id in ( Select Id From Table2)

You basically described an inner join with selection of rows from one table:
var result = from t1 in Table1
join t2 in Table2
on t1.Id equals t2.Id
select new{t1.Id, t1.Name};
Next SQL statement will be generated using EF and MS SQL:
SELECT t1.Id, t1.Name
FROM Table1 AS t1
INNER JOIN Table2 AS t2 ON t1.Id = t2.Id
Note, that if you are selecting non-unique items from Table2, you can potentially have duplicates in the result. Use next query to avoid this problem, cons: it loads all ids from Table2 into memory, pros: more time efficient. Checkout Felipes answer's, which is also quite good, but has it's own cons discussed in the comment section.
var table2Ids = new HashSet<int>(context.Table2.Select(t2 => t2.Id));
var result = context.Table1
.Where(t => table2Ids.Contains(t.Id))
.Select(t => new{t.Id, t.Name});

try using the Contains method:
var query = from c in db.Table1
where db.Table2.Select(x => x.Id).Contains(c.Id)
select new { c.Id, c.Name };
var result = query.ToList();

Related

Query multiple tables with LINQ, grab results to dictionary

I have this simple SQL:
SELECT name, value
FROM table1 t1, table2 t2
WHERE t1.id = t2.id
AND t1.id = 123
How do I convert it to LINQ in C#, so that the results are in Dictionary?
I'm guessing you are using Entity Framework?
Could you use RelationShips instead?
Or like this:
var query = from t1 in context.Table1
from t2 in context.Table2
where t1.Id == t2.Id
select new { t1.name, t2.value};
var result = query.ToList();
var dir = result.ToDictionary(x => x.name, x => x.value);
https://learn.microsoft.com/en-us/ef/core/querying/complex-query-operators

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{};

Join in LINQ and Entity Framework

In SQL I to get the distinct statement, I used join to get it as below
select distinct
col1
from
table1 a
inner join
table2 b on a.code = b.vcode
How can the same be implemented in LINQ over Entity Framework?
Please suggest me.
You can also use method syntax:
var query = table1.Join(table2,
a => a.code,
b => b.vcode,
(a,b) => a.col1)
.Distinct();
var result = (from a in table1
join b in table2 on a.code equals b.vcode
select a.col1).Distinct();

Return all columns in anonymous linq join

How do I return all the columns in the following anonymous linq join:
var results = (from t in Table1.AsEnumerable() join t2 in Table2.AsEnumerable()
on t.Field<string>("id") equals t2.Field<string>("id")
into allcol from rows in allcol
select rows);
I am getting allow rows from Table2, and no rows from Table1
var results = (from t in Table1.AsEnumerable()
join t2 in Table2.AsEnumerable()
on t.Field<string>("id")
equals t2.Field<string>("id")
into allcol
from rows in allcol
select new {table1=t,table2=rows});
I hope this will help.

How to rewrite this linq query correctly?

int id =2 ;
(from t1 in Table1
join t2 in Table2
on new { t1.id, id} equals new { t2.id, t2.otherid }
select t1).ToList();
Currently the above query gives me a compilation error saying
The type on one of the join expressions is incorrect.
As you can see in the above query I want to join on a single integer value as you would in sql. I want to these so that query is faster and I don't want to do a where at the end because that would mean it will get all the rows and then filter with the where clause. As I have lot of rows in both the tables it would be good if I can filter rows on join clause itself. Thanks for your help !
You need to use the same anonymous type (with the same property names) in both halves of the join:
on new { t1.id, otherId = 2 } equals new { t2.id, t2.otherId }
Your text implies that you actually want to join on a single value; if so, you don't need an anonymous type at all:
on t1.id equals t2.otherid
When you join using an anonymous classes, the members of those class' names must match. The problem is easily solved by adding names to your anonymous class' members:
int id = 2;
(from t1 in Table1
join t2 in Table2
on new { Id = t1.id, OtherId = id }
equals new { Id = t2.id, OtherId = t2.otherid }
select t1).ToList();
Although, the more I look at it the more I realize that the join doesn't need to be that complex. It looks like you're adding the static id in the join. You should be able to get away with it in the where clause which would reduce the join to a single value:
int id = 2;
(from t1 in Table1
from t2 in Table2
on t1.id equals t2.id
where t2.otherid = id
select t1).ToList();
I see two possible solutions:
This variant prefilters Table2, then performs the join.
int id =2;
(from t1 in Table1
join t2 in (from a in Table2 where a.otherid == id select a)
on t1.id equals t2.id
select t1).ToList();
Here is a debugged variant of your original code. Because the compiler uses the property names when creating anonymous objects, you have to be explicit about the names.
int id =2;
(from t1 in Table1
join t2 in Table2
on new { Id1 = t1.id, Id2 = id } equals new { Id1 = t2.id, Id2 = t2.otherid }
select t1).ToList();
HTH, Mark

Categories