I want to change sql query to linq using join statement. The query should retrieve columns (days and startdate) while matching records of table 1 to table. In short converting sql query to linq using join statement.
Below is what i've tried.
SQL Query (Working)
SELECT *
FROM dbo."Batches"
INNER JOIN dbo.StudentBatchRelation
on dbo.Batches.Id = dbo.StudentBatchRelation.BatchId
WHERE
dbo.StudentBatchRelation.StudentId = '3d980306-e36e-4581-8c98-219717cb1668'
LINQ (not fetching result)
var result = (from t1 in contBatch.GetallBatchList()
join t2 in contStudent.getAllStudentBatchList()
on t1.Id equals t2.batchId where t2.studentId == studentid
select new { t1.Days, t1.BatchDate }).ToList();
If your EF entities are well defined, you could simplify your query with :
var result = Db.Batches
.Include(p => p.StudentBatchRelation)
.Where(p => p.StudentBatchRelation.StudentId = "3d980306-e36e-4581-8c98-219717cb1668")
.ToList();
Otherwise, if you have to use your Getallxxxx functions, you could do :
var result = (from t1 in contBatch.GetallBatchList()
join t2 in contStudent.getAllStudentBatchList()
on t1.Id equals t2.batchId
where t2.studentId == "3d980306-e36e-4581-8c98-219717cb1668"
select t1)
.ToList();
Related
I can I generate the below SQL query select using entity framework core 3.1.8 ?
SELECT *
FROM table1 t1
LEFT JOIN table2 t2 ON t1.Id = t2.table1Id AND t2.Status IN (1,2,3)
I tried the code below
var statuses = new List<int> { 1, 2, 3 };
var result = await (from t1 in _context.Table1
join t2 in _context.Table2
on t1.Id equals t2.TableId
into results
from m in results.Where(x => statuses.Contains((int)x.Status)).DefaultIfEmpty()
select new ResultDto
{
}).ToListAsync();
But the query generates a suquery
UPDATED
The query suggested by
#Svyatoslav Danyliv generated the SQL below
SELECT [a].[Id], [a].[ActionWith], [a].[CreatedBy], [a].[DateCreated], [t].[table1Id], [t].[Comment], [t].[CreatedBy], [t].[DateCreated]
FROM [Table1] AS [a]
LEFT JOIN (
SELECT [c].[Id], [c].[table1Id], [c].[Comment], [c].[CreatedBy], [c].[DateCreated]
FROM [Table2] AS [c]
WHERE [c].[Status] IN (1, 2)
) AS [t] ON [a].[Id] = [t].[table1Id]
As documented in Collection selector references outer in a where clause, you can rewrite your query in the following way:
var query =
from t1 in _context.Table1
from t2 in _context.Table2
.Where(t1 => t1.Id == t2.TableId && statuses.Contains((int)x.Status))
.DefaultIfEmpty()
select new ResultDto
{
}
Note that GroupJoin has limited translation in EF Core, only simple LEFT JOIN.
I am trying to write a linq query that resembles this SQL:
SELECT * FROM Table1
WHERE EXISTS (
SELECT 1 FROM Table2
WHERE Table1.ColA = Table2.ColA
AND Table1.ColB = Table2.ColB
)
Except Table2 is an object list I already have previously from the database.
I know how to use contains() to emulate an SQL "IN SUBQUERY" using a object list outside of the database when one column is involved:
var query = from t1 in db.Table1
where MyObjList.Select(o => o.Field1).Contains(t1.Col1)
select t1;
I figure I can do a join in Linq. But will that perform ok? I hope avoid a database call per object in my list.
var q = from t1 in db.Table1
from t2 in db.Table2.Where(x => x.ColA == t1.ColA && x.ColB == t1.ColB)
select t1;
Try like this:
var query = from t1 in db.Table1
join t2 in db.Table2 on t1.ColA equals t2.ColA
Where t1.ColB == t2.ColB
Select t1;
OR without Join
var query = from t1 in db.Table1
from t2 in db.Table2
Where t1.ColA == t2.ColA && t1.ColB == t2.ColB
Select t1;
T-SQL:
declare #postlocations table (locationid int)
insert into #postlocations
select locationid
from dbo.PostLocations
where PostId = 162172
select t.*
from dbo.Themes t
inner join dbo.ThemeLocations tl on t.ThemeId = tl.ThemeId
inner join #postlocations pl on tl.LocationId = pl.locationid
LINQ-Entities i have so far:
var postLocations = e.SomePost.Locations; // pre-fetched, e.g materialized ICollection<Post>
var themes = (from t in db.Themes
join q in postLocations on t.Locations.Select(l => l.LocationId) equals q.LocationId
select t).ToList();
But the compiler is complaining on the join keyword about not being able to infer the type arguments.
Any ideas?
I don't think you can join a SQL table with an in-memory list of objects, even if those objects are originally from the database.
Convert the in-memory list of objects to a list of id's (integer), and use that in the join or in a Contains/sub-select. EF can translate the list of id's to parameters when generating the SQL.
The problem with your join is that you're implying a collection of LocationId (t.Locations.Select(l => l.LocationId) can equal a single LocationId. You're trying to join a Theme which has a collection of Locations onto a single Location.
You should be able to fix this by using Contains
var themes = (from t in db.Themes
join q in postLocations
on t.Locations.Select(l => l.LocationId).Contains(q.LocationId)
select t).ToList();
or if EF complains about passing a postLocations as a parameter, you can try
// I'd materialize this but you may not have to
var postLocationIds = postLocations.Select(p => p.LocationId).ToList();
var themes = db.Themes.Where(t => t.Locations.Any(l =>
postLocationIds.Contains(l.LocationId))).ToList();
Edit
how about this
///your sql query
select t.* from dbo.Themes t
inner join dbo.ThemeLocations tl on t.ThemeId = tl.ThemeId
inner join #postlocations pl on tl.LocationId = pl.locationid
//linq query for that
from t in teams
join from tl in teamlocation on t.themid = tl.ThemeID
join from pl in postlocation on tl.temeid = pl.temeid
select t;
Org
Not sure but you can try out by using let keyword
var themes = (from t in db.Themes
let location = t.Locations
join q in postLocations on location.LocationId equals q.LocationId
select t).ToList();
I am trying to create query which orders by child collection's property. It is quite easy in SQL:
Select Table1.*
From Table1
Inner join Table2 on Table1.Id = Table2.Table1Id
OrderBy Table1.Column1, Table2.Column1
Here is how I did it in NHibernate 2 and it worked fine:
var result = Session.Linq<Table1>()
.OrderBy(x => x.Column1)
.ThenBy(x => x.Table2.FirstOrDefault().Column1);
After migrating to NHibernate 3 this doesn't work anymore. It throws NHibernate.Hql.Ast.ANTLR.QuerySyntaxException: Antlr.Runtime.NoViableAltException.
I am using NHibernate 3.1. Are there other solutions for such query?
The two queries aren't the same. The LINQ version (roughly) equates to:
SELECT Table1.*
FROM Table1
INNER JOIN (SELECT TOP 1 * FROM Table2 WHERE Table2.Table1ID = Table1.Id) AS FirstTable2
ORDER BY Table1.Colum1, FirstTable2.Table2
EDIT
If you want to replicate the original sql you might want something like:
Session.Linq<Table1>()
.SelectMany(t1 => t1.Table2, (t1,t2) => new { t1, t2 })
.OrderBy(t1t2 => t1t2.t1.Column1)
.ThenBy(t1t2 => t1t2.t2.Column2)
.Select(t1t2 => t1)
var result = table1.Join(table2, o => o.ProgramID, t => t.ProgramID, (o, t) => new { o.ProgramID, t.Program })
.OrderBy(t => t.Program)
.Distinct();
the above linq statement actually returns the correct result, but he sql generated (below) is not as simple as it could be
SELECT [t2].[ProgramID], [t2].[Program]
FROM (
SELECT DISTINCT [t0].[ProgramID], [t1].[Program]
FROM [table1] AS [t0]
INNER JOIN [table2] AS [t1] ON [t0].[ProgramID] = [t1].[ProgramID]
) AS [t2]
ORDER BY [t2].[Program]
I would have thought the sql below is far cleaner but I'm not sure of the linq statement to achieve it.
select distinct
o.ProgramID,
t.Program
from
table1 0
inner join table2 t on t.ProgramID = o.ProgramID
order by t.Program
Thanks in advance
I don't know if it will help, but you can try something like this;
var result = (from o in table1
join t in table2 on o.ProgramID equals t.ProgramID
orderby t.Program
select new { o.ProgramID, t.Program }).Distinct();
I tried this and that works:
var result = (from o in table1
join t in table2 on o.ProgramID equals t.ProgramID
select new { o.ProgramID, t.Program })
.Distinct().OrderBy(t => t.Program)
.ThenBy(t => t.ProgramName)
.ThenBy(t => t.Description);
First you do Distinct and then OrderBy, then OrderBy works.
Profile the two queries, comparing stats-IO and the actual execution plan. It is entirely possible that it makes zero difference to the SQL server.
If you really want known TSQL, use ExecuteQuery-of-T and pass in the TSQL yourself. Maybe include some lock hints too (most commonly: NOLOCK)