How to use leftouter join in entity framework query
I have two table one is item and other is stock available I want to get all items and also get its quantity from stock available table which depend upon the particular department
For example
LINQ Query
var query = (from p in dc.GetTable<Person>()
join pa in dc.GetTable<PersonAddress>() on p.Id equals pa.PersonId into tempAddresses
from addresses in tempAddresses.DefaultIfEmpty()
select new { p.FirstName, p.LastName, addresses.State });
SQL Translation
SELECT [t0].[FirstName], [t0].[LastName], [t1].[State] AS [State]
FROM [dbo].[Person] AS [t0]
LEFT OUTER JOIN [dbo].[PersonAddress] AS [t1] ON [t0].[Id] = [t1].[PersonID]
Related
I have prepared a SQL query and I'm having problem translating into LINQ query. Below I'm attaching my SQL query.
I have problems with inner join and left join that contains a select inside, and actually a second left join has another select inside a select as well, with group by.
This is really frustrating so maybe you could help me?
select * from Users u
inner join Pickups p on p.Number=u.Number
inner join Revisions r on r.Id=p.RevisionId and r.RevisionText='Done'
inner join (select u2.Id, count(u2.Id) clicks_num
from Users u2
inner join Clicks uc on uc.UserId=u2.Id
group by u2.Id) clicks on clicks.Id=u.Id
left join (select UserId, count(Id) scc
from (select distinct ucx.UserId, ucx.Id
from Clicks ucx
inner join Pickups ucpx on ucpx.Number=ucx.Number
inner join Revisions ucprx on ucprx.Id=ucpx.RevisionId and r.RevisionText='Done') t
group by UserId) s on s.UserId = u.Id
where clicks.clicks_num = s.scc;
I am starting with a simple one, but then could you give me an example how to make an inner select as join?
from u in Context.Set<Users>()
join p in Context.Set<Pickups>() on u.Number equals p.Number
join r in Context.Set<Revisions>() on p.RevisionId equals r.RevisionId
I have struggling to run linq left on multiple tables.
tableA
Select all the (courseID, code, title) from courseInstances table
tableB
select (studyLevel_ID) from Courses table where courseID from tableA = CourseID from tableB. tableB has courseID
tableC
Select (StudyLevelDescription) from StudyLevel table where studyLevelID from tableB = studyLevel from tableC.
I believe I need left join on table A as I need all the records
I have done separate linq which are working fine but struggling to bring combine result
CourseInstances results
var processedCourseInstance =
(from _courseInstances in _uof.CourseInstances_Repository.GetAll()
join _courses in _uof.Courses_Repository.GetAll() on _courseInstances.CourseID equals _courses.CourseID
into a from b in a.DefaultIfEmpty()
orderby _courseInstances.CourseCode
select _courseInstances).ToList();
StudyLevel results for each course
var _CoursesStudyLevel_Lookup =
(from _course in _uof.Courses_Repository.GetAll()
join _studyLevel in _uof.StudyLevel_Repository.GetAll() on _course.StudyLevelId equals _studyLevel.StudyLevelID
select new {_course.CourseID, _course.StudyLevelId, _studyLevel.LevelDescription }).ToList();
I have managed to combine two results but NOT with LEFT join on CourseInstance table. This time I used LINQPad
from _courseInstances in CourseInstances
join _courses in Courses on _courseInstances.CourseID equals _courses.CourseID
join _studylevel in StudyLevels on _courses.StudyLevelId equals _studylevel.StudyLevelID
orderby _courseInstances.CourseCode
select new {_courseInstances.CourseID, _courseInstances.CourseCode, _courseInstances.CourseTitle, _courseInstances.UCASCode, _courses.StudyLevelId, _studylevel.LevelDescription, _studylevel.SLevelType }
for above SQL version as following;
SELECT [t0].[CourseID], [t0].[CourseCode], [t0].[CourseTitle],
[t0].[UCASCode], [t1].[StudyLevelId], [t2].[LevelDescription], [t2].[SLevelType]
FROM [CourseInstances] AS [t0]
INNER JOIN [Courses] AS [t1] ON [t0].[CourseID] = ([t1].[CourseID])
INNER JOIN [StudyLevel] AS [t2] ON [t1].[StudyLevelId] = ([t2].[StudyLevelID])
ORDER BY [t0].[CourseCode]
If i understand correctly, you want something like this?
from _courseInstances in CourseInstances
join c in Courses on _courseInstances.CourseID equals c.CourseID into courses
from _courses in courses.DefaultIfEmpty()
join sl in StudyLevels on _courses.StudyLevelId equals sl.StudyLevelID into studyLevels
from _studylevel in studyLevels.DefaultIfEmtpy()
orderby _courseInstances.CourseCode
select new {
_courseInstances.CourseID,
_courseInstances.CourseCode,
_courseInstances.CourseTitle,
_courseInstances.UCASCode,
_courses.StudyLevelId,
_studylevel.LevelDescription,
_studylevel.SLevelType
}
}
You can create a LINQ left join query with the into keyword and .DefaultIfEmpt().
I was working with the first method below, but then I found the second and want to know the difference and which is best.
What is the difference between:
from a in this.dataContext.reglements
join b in this.dataContext.Clients on a.Id_client equals b.Id
select...
and
from a in this.dataContext.reglements
from b in this.dataContext.Clients
where a.Id_client == b.Id
select...
I created a test case to test out the difference, and in your scenerio it turns out they are the same.
My test example used AdventureWorks but basically there is an association between
Products->CategoryId->Categories
var q = (
from p in Products
from c in Categories
where p.CategoryID==c.CategoryID
select p
);
q.ToList();
Produces this SQL:
SELECT [t0].[ProductID], [t0].[ProductName], [t0].[CategoryID]
FROM [Products] AS [t0], [Categories] AS [t1]
WHERE [t0].[CategoryID] = ([t1].[CategoryID])
var q2 = (
from p in Products
join c in Categories
on p.CategoryID equals c.CategoryID
select p);
q2.ToList();
Produces this sql:
SELECT [t0].[ProductID], [t0].[ProductName], [t0].[CategoryID]
FROM [Products] AS [t0]
INNER JOIN [Categories] AS [t1] ON [t0].[CategoryID] = ([t1].[CategoryID])
The difference between these two syntaxes will be in the way they are translated into SQL. You can trace Entity Framework or LINQ to SQL to determine the SQL:
LINQ to SQL: http://www.reflectionit.nl/Blog/PermaLinkcba15978-c792-44c9-aff2-26dbcc0da81e.aspx
Check the resulting SQL to determine if there are any differences that could affect performance.
I need help generating a more efficient LINQ query:
Table: Positions
-PositionID
-Name
Table: Person
-PersonID
-Name, etc...
Table: PersonPosition
-PersonID
-PositionID
I need a result set that groups the people assigned to each position:
PositionID Person
1 John
Bob
Frank
2 Bill
Tom
Frank, etc...
My first thought was this LINQ query:
from perspos in PersonPositions
join pers in Persons on perspos.PersonID equals pers.PersonID
group pers by perspos.PositionID into groups
select new {groups.Key, groups}
Which works great, but produces the following SQL:
SELECT [t0].[PositionID] AS [Key]
FROM [PersonPosition] AS [t0]
INNER JOIN [Person] AS [t1] ON [t0].[PersonID] = [t1].[PersonID]
GROUP BY [t0].[PositionID]
GO
-- Region Parameters
DECLARE #x1 Int = 3
-- EndRegion
SELECT [t1].[PersonID], [t1].[UserID], [t1].[Firstname], [t1].[Lastname], [t1].[Email], [t1].[Phone], [t1].[Mobile], [t1].[Comment], [t1].[Permissions]
FROM [PersonPosition] AS [t0]
INNER JOIN [Person] AS [t1] ON [t0].[PersonID] = [t1].[PersonID]
WHERE #x1 = [t0].[PositionID]
GO
-- Region Parameters
DECLARE #x1 Int = 4
-- EndRegion
SELECT [t1].[PersonID], [t1].[UserID], [t1].[Firstname], [t1].[Lastname], [t1].[Email], [t1].[Phone], [t1].[Mobile], [t1].[Comment], [t1].[Permissions]
FROM [PersonPosition] AS [t0]
INNER JOIN [Person] AS [t1] ON [t0].[PersonID] = [t1].[PersonID]
WHERE #x1 = [t0].[PositionID]
GO
-- Region Parameters
DECLARE #x1 Int = 5
-- EndRegion
SELECT [t1].[PersonID], [t1].[UserID], [t1].[Firstname], [t1].[Lastname], [t1].[Email], [t1].[Phone], [t1].[Mobile], [t1].[Comment], [t1].[Permissions]
FROM [PersonPosition] AS [t0]
INNER JOIN [Person] AS [t1] ON [t0].[PersonID] = [t1].[PersonID]
WHERE #x1 = [t0].[PositionID]
GO
on and on...
Is there a better LINQ query that translates to a more efficient SQL statement?
You should already have the relationship defined in your database, and also on your dbml.
Avoid doing joins when you don't have to; they are really tedious. Let LINQ-to-SQL do this for you. Something like this should work:
var data = context.PersonPositions
.Select(pos => new { pos.PositionID, pos.Person });
return data.GroupBy(pos => pos.PositionID);
or
return context.Positions.Select(pos =>
new { pos, pos.PersonPositions.Select(pp => pp.Person).ToList() }).ToList();
I'm fairly sure you have to just join the tables and select the result, then call .AsEnumerable(), and group after that:
(from perspos in PersonPositions
join pers in Persons
on perspos.PersonID equals pers.PersonID
select new { perspos.PositionID, Person = pers })
.AsEnumerable().GroupBy(p => p.PositionID, p => p.Person);
I"m having some problems with Nhibernate and native sql.
I've got an entity with alot of collections and I am doing an SQL Fulltext search on it. So when returning 100 or so entities, I dont want all collections be lazy loaded. For this I changed my SQL query:
SELECT Query.*
FROM (SELECT {spr.*},
{adr.*},
{adrt.*},
{cty.*},
{com.*},
{comt.*},
spft.[Rank] AS [Rak],
Row_number() OVER(ORDER BY spft.[Rank] DESC) AS rownum
FROM customer spr
INNER JOIN CONTAINSTABLE ( customerfulltext , computedfulltextindex , '" + parsedSearchTerm + #"' ) AS spft
ON spr.customerid = spft.[Key]
LEFT JOIN [Address] adr
ON adr.customerid = spr.customerid
INNER JOIN [AddressType] adrt
ON adrt.addresstypeid = adr.addresstypeid
INNER JOIN [City] cty
ON cty.cityid = adr.cityid
LEFT JOIN [Communication] com
ON com.customerid = spr.customerid
INNER JOIN [CommunicationType] comt
ON comt.communicationtypeid = com.communicationtypeid) as Query
ORDER BY Query.[Rank] DESC
This is how I setup the query:
var items = GetCurrentSession()
.CreateSQLQuery(query)
.AddEntity("spr", typeof(Customer))
.AddJoin("adr", "spr.addresses")
.AddJoin("adrt", "adr.Type")
.AddJoin("cty", "adr.City")
.AddJoin("com", "spr.communicationItems")
.AddJoin("comt", "com.Type")
.List<Customer>();
What happens now is, that the query returns customers twice (or more), I assume this is because of the joins since for each customer address, communicationItem (e.g. phone, email), a new sql row is returned. In this case I thought I could use the DistinctRootEntityResultTransformer.
var items = GetCurrentSession()
.CreateSQLQuery(query)
.AddEntity("spr", typeof(Customer))
.AddJoin("adr", "spr.addresses")
.AddJoin("adrt", "adr.Type")
.AddJoin("cty", "adr.City")
.AddJoin("com", "spr.communicationItems")
.AddJoin("comt", "com.Type")
.SetResultTransformer(new DistinctRootEntityResultTransformer())
.List<Customer>();
Doing so an exception is thrown. This is because I try to list customers .List<Customer>() but the transformer returns only entities of the last join added. E.g. in the case above, the entity with alias "comt" is returned when doing .List() instead of .List<Customer>(). If I would switch last join with the join alias "cty", then the transformer returns a list of cities only...
Anyone knows how I can return a clean list of customers in this case?
try this
var items = GetCurrentSession()
.CreateSQLQuery(query)
.AddEntity("spr", typeof(Customer))
.AddJoin("adr", "spr.addresses")
.AddJoin("adrt", "adr.Type")
.AddJoin("cty", "adr.City")
.AddJoin("com", "spr.communicationItems")
.AddJoin("comt", "com.Type")
.AddEntity("spr", typeof(Customer))
.SetResultTransformer(new DistinctRootEntityResultTransformer())
.List<Customer>();
GetCurrentSession.CreateQuery("select distinct spr from Customer spr inner join spr.Addresses
adr inner join adr.Type adrt inner join adr.City cty inner join apr.CommunicationItems com
inner join com.Type comt").List<Customer>();
Hope this helps. Or you can write the desired SQL query under
GetCurrentSession.CreateSqlQuery(sqlquery).List<Customer>();