Convert a SQL query to LINQ query - sql

I have the following SQL query
SELECT *
FROM LOC l
JOIN CLA c ON l.IdLoc = c.IdLoc
JOIN FA f on c.IdCla = f.IdCla
LEFT JOIN CON co ON f.IdCla = co.IdCla
AND co.DeletedDate IS NULL
AND co.IdUser = f.IdUser
WHERE f.IdUser = 7
AND f.DeletedDate IS NULL
I would like to convert it to LINQ but I'm absolutely not at ease with LEFT JOIN and "temp table" with LINQ.
Moreover, I tried to convert it but it seems it is impossible to create a join clause with a WHERE inside in LINQ (Linqer told me that and Linqpad doesn't seem able to convert from SQL to LINQ in free version)
Could you give me clue ?
Thanks a lot

I think you are looking for something like this. I left out the select clause so that you can pull out what you need. Things to note:
To join multiple columns, create anonymous types. The field names in the anonymous types must match.
To create a =NULL condition, create a variable name that matches the field name in the other entity. Set it =null but coerce it to the nullable data type of the field you are setting it equal to.
Edit: Updated query to move where clause to joins
from l in LOC
join c in CLA
on l.IdLoc equals c.IdLoc
join f in FA
on new { c.IdCla, IdUser = 7, DeletedDate = (DateTime?)null }
equals new { f.IdCla, f.IdUser, f.DeletedDate }
join co in CON
on new { f.IdCla, DeletedDate = (DateTime?)null, f.IdUser }
equals new { co.IdCla, co.DeletedDate, co.IdUser } into lj
from l in lj.DefaultIfEmpty()

Related

LINQ to Entities returns empty list but it's SQL equivalent returns results

I'm sure this is something fairly common... I'm joining two entities with a mapping table and attempting to load back all relationships.
public IEnumerable<Clinic> ClientClinics(Guid clientId)
{
var clinics =
from c in _appDbContext.Clinics
join ccm in _appDbContext.ClientClinicMappings on c.ClinicId equals ccm.ClinicId
join cli in _appDbContext.Clients on ccm.ClientId equals cli.ClientId
where cli.ClientId == clientId && !c.DeletedAt.HasValue
select c;
return clinics.ToList();
}
I'm getting no results when I should be... I turned on the db logging and here's the generated SQL:
SELECT [c].[ClinicId], [c].[Address], [c].[City], [c].[CreatedAt], [c].[CreatedBy], [c].[DeletedAt], [c].[DeletedBy], [c].[ModifiedAt], [c].[ModifiedBy], [c].[Name], [c].[Phone], [c].[State], [c].[Zip]
FROM [Clinic] AS [c]
INNER JOIN [ClientClinicMapping] AS [ccm] ON [c].[ClinicId] = [ccm].[ClinicId]
INNER JOIN [Client] AS [cli] ON [ccm].[ClientId] = [cli].[ClientId]
WHERE ([cli].[ClientId] = #__clientId_0) AND [c].[DeletedAt] IS NULL
When I paste in my GUID that I'm searching with, I'm able to get results from SQL.
Anyone have any suggestions to where I should be looking or what to be trying?

Querydsl: how to make left join by column

Im trying to match this SQL query in querydsl
SELECT tr.* FROM test.TRIP_REQ tr left outer join test.ADDR_BOOK ab on tr.REQ_USERID=ab.USER_ID
I know how to make left join query if you join into identity column but struggle to make it work with joining on 2 alternative columns. tr.REQ_USERID and ab.USER_ID are not identity columns
This is my querydsl:
QTripReq qTripReq = QTripReq.tripReq;
QAddressBook qABook = QAddressBook.addressBook;
JPAQuery query = new JPAQuery(entityManager);
query.from(qTripReq).leftJoin(qABook).on(qTripReq.requestorUser.id.eq(qABook.user.id)).list(qTripReq);
This throws error:
Path expected for join! [select tripReq from com.TripReq tripReq left join ADDR_BOOK addressBook with tripReq.requestorUser.id = addressBook.user.id where tripReq.assignedCompany.id = ?1]
You need to add a target entity path to leftJoin(), so that
QTripReq qTripReq = QTripReq.tripReq;
QAddressBook qABook = QAddressBook.addressBook;
JPAQuery query = new JPAQuery(entityManager);
query.from(qTripReq).leftJoin(qTripReq.addressBook, qABook).on(qTripReq.requestorUser.id.eq(qABook.user.id)).list(qTripReq);
Take a look on Using joins section in docs.

Unable to convert SQL Query to LINQ Query for Left Outer Join

Problem Statement:
I'm trying to convert one of my Sql to linq query, but I'm unable to get the desired output which i need. Can anyone suggest me what i should do?
SQL Query:
SELECT AssetTagging.AssetID, AssetTagging.AssetDescription, [Return].RequestStatus
FROM AssetTagging
LEFT OUTER JOIN [Return] ON AssetTagging.AssetID = [Return].AssetID
LEFT OUTER JOIN Issue ON AssetTagging.AssetID = Issue.AssetID
WHERE (Issue.AssetID IS NULL) OR ([Return].RequestStatus = 'Approved')
Linq Query I'm using:
var result = (from at in db.AssetTagging.AsEnumerable()
join r in db.Return on at.AssetID equals r.AssetID
orderby at.AssetID
where !db.Issue.Any(issue=>issue.AssetID==at.AssetID) || r.RequestStatus=="Approved"
select new globalTestModel
{
model1=at
}).ToList();
//I know that in Linq query I'm using Inner join instead of Left Join,but i'm getting error if i use left join instead of inner join?
What am I doing wrong??
Any suggestion to get desired query like Sql in Linq?
Asset Tag table:
Issue table:
Return table:
Desired Output :
You need to remove .AsEnumerable(), because you want your query to be translated to sql. Right now it would be using linq-to-objects and if you are using a left join with linq-to-object you need to check for null reference exceptions. rt could be null, so rt.RequestStatus would throw an exception.
*I believe rt should be r in your example
You can't project to an existing entity, so you need to change your select to:
select new PocoClass
{
model1=at
}
//New class definition
public PocoClass
{
public AssetTagging model1 { get; set; }
}
You need to do like this:
var result = from at in db.AssetTagging
join r in db.Returns on at.AssetID equals r.AssetID into a
from returns into a.DefaultIfEmpty()
join i in db.Issues on at.AssetID equals I.AssetID into b
from issues into b.DefaultIfEmpty()
where issues.AssetID != null || returns.RequestStatus == "Approved"
select new
{
AssetID = at.AssetID,
AssetDescription = at.AssetDescription,
Status = returns != null ? returns.RequestStatus : null
}.ToList();
try like following:
from at in db.AssetTagging
join r in db.Return on at.AssetID equals r.AssetID into res1
from atr in res1.DefaultIfEmpty()
join i in db.Issues on i.AssetID==at.AssetID into res2
from obj in res2.DefaultIfEmpty()
select at
where i.AssetID == null || r.RequestStatus equals "Approved"
Just make two times left outer join and then do filter on where condition.
Also have first look at this msdn article about left outer join using linq.
Try the following I am assuming that you still want the cases where r is null unless r is not null and request status = approved.
You have to check to verify r!=null before checking the request status and you will still need to include when r is null to get the complete result set. I haven't tested this, but this should put you in the right direction.
Good luck.
var result = (from at in db.AssetTagging
join r in db.Return.DefaultIfEmpty()
on at.AssetID equals r.AssetID
join i in db.Issue.DefaultIfEmpty()
on at.AssetID equals i.AssetID
where
(r == null || (r!=null && r.RequestStatus == "Approved"))
|| i == null
select new {
at.AssetID,
at.AssetDescription,
IssueID = (i!=null) ? i.IssueID : null),
ReturnID = (r!=null) ? r.ReturnID: null),
ReturnStatus = (r!=null)
? r.ReturnStatus
: null}).ToList();
I know this isn't exactly what you've asked for, but it might be useful anyway.
If you have access to the database to execute SQL queries, I would suggest creating a view. You can then drop the view into your DBML file the same way as you would with a table, and have much simpler Linq expressions in your C# code.
CREATE VIEW [Asset_Issue_Return_Joined] AS
SELECT AssetTagging.AssetID, AssetTagging.AssetDescription, [Return].RequestStatus
FROM AssetTagging
LEFT OUTER JOIN [Return] ON AssetTagging.AssetID = [Return].AssetID
LEFT OUTER JOIN Issue ON AssetTagging.AssetID = Issue.AssetID
WHERE (Issue.AssetID IS NULL) OR ([Return].RequestStatus = 'Approved')
Here is the complete query
var result = (from assetTagging in db.AssetTagging
join return0 in db.Return on assetTagging.AssetID equals return0.AssetID into returns
from return0 in returns.DefaultIfEmpty()
join issue in db.Issue on assetTagging.AssetID equals issue.AssetID into issues
from issue in issues.DefaultIfEmpty()
where issue.AssetID == null || return0.RequestStatus == "Approved"
select new
{
assetTagging.AssetID,
assetTagging.AssetDescription,
return0.RequestStatus
}).ToList();

Spatial Join in Entity Framework

I want to write a join statement in LINQ using the dbgeography's "Intersects" method (I am using EF June 2011 CTP). The problem is if I write something like this:
var joinQuery = from spQ in spatialTableQuery
join mnQ in MainQuery
on spQ.Polygon.Intersects(mnQ.PointGeography) equals 1
I get the following error:
The name 'mnQ' is not in scope on the left side of 'equals'. Consider
swapping the expressions on either side of 'equals'.
In SQL I have written a similar query as below so I know SQL suppports it:
SELECT * FROM Address a
INNER JOIN SPATIALTABLE b
WITH(INDEX(geog_sidx))
ON b.geom.STIntersects(a.PointGeography) = 1
Try something like this:
var joinQuery =
from spQ in spatialTableQuery
from mnQ in MainQuery
where spQ.Polygon.Intersects(mnQ.PointGeography) = 1

How do I pass a parameter from the select list into a function for joining a linq query?

I have a query that can be summarised in SQL as follows;
Select
S.StockCode
From
StockToCheck As S
Inner Join
GetPOSStock(S.StockCode) As C
On S.StockCode = C.StockCode;
I'm trying to do the same in Linq but it seems I cannot pass a parameter to the function I am joining on as it has not been parsed by Linq.
I imagine it would look like this (vb);
Dim x = From S In StockToCheck
Join C In GetPOSStock(S) On S Equals C.ProductCode
Where the S var is a list of strings. This gives the error 'S' is not declared and points to the S in the function call / join (GetPOSStock). So it does not seem possible to do this in Linq, can anyone confirm?
Thanks in advance
Ryan
The following worked for me:
Using dc As New TestDC
Dim x = From s In dc.Stocks
From c In dc.GetPOSStock(s.Code)
Where s.Code = c.Code
Select s.Code
End Using
I assumed that GetPOSStock is a table-valued function in your DB, so I created one accordingly. I also created separate classes for Stock and for POSStock and assigned POSStock as the return value for GetPOSStock using Linq-to-SQL designer.