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

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?

Related

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();

Convert a SQL query to LINQ query

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()

SQL Query: Comparing two dates in returned record

I'm trying to come up with an automated solution for something I do manually now and I only have minimal, bare-bones SQL skill. I usually modify simple queries others have built or will build basic select queries. I have done some reading but don't know how to make it do what I need in this case. I need to come up with something others can use while I am out for a month (and which will save me time when I return).
What I need is to return the fields below where tblThree.EndDate is later than tblFive.ServiceEnd. I have to do a couple of other compares on the dates, but if I get a working query of the first one I can make it work with the others. We use MS SQL Server 2008.
I tried creating sub-queries with aliases and failed miserably at making it work.
These are the table and fields I am working with:
tblOne.ServiceID
tblOne.ServiceYear
tblOne.Status
tblTwo.AccountNbr
tblTwo.AcctName
tblThree.BeginDate (smalldatetime, null)
tblThree.EndDate (smalldatetime, null)
tblFour.ClientID
tblFour.ServiceName
tblFive.ContractID
tblFive.ServiceBegin (smalldatetime, null)
tblFive.ServiceEnd (smalldatetime, null)
This is how the tables are related:
tblOne.ServiceID = tblThree.ServiceID
tblOne.ContractID = tblFive.ContractID
tblOne.ClientID = tblFour.ClientID
tblTwo.AccountNbr = tblFour.Account
I used MS Access 2003 to generate the Join SQL:
SELECT tblOne.ServiceID, tblTwo.AccountNbr,
tblTwo.AcctName, tblFour.ServiceName, tblOne.Status,
tblThree.BeginDate, tblThree.EndDate,
tblOne.ServiceYear, tblFive.ServiceBegin,
tblFive.ServiceEnd
FROM ((tblTwo INNER JOIN tblFour
ON tblTwo.AccountNbr=tblFour.AccountNbr) INNER JOIN (tblThree INNER JOIN tblOne
ON tblThree.ServiceID=tblOne.ServiceID)
ON tblFour.ClientID=tblOne.ClientID) INNER JOIN tblFive
ON tblOne.ContractID=tblFive.ContractID;
Thanks for any help.
Just add a WHERE clause to get started:
SELECT tblOne.ServiceID, tblTwo.AccountNbr,
tblTwo.AcctName, tblFour.ServiceName, tblOne.Status,
tblThree.BeginDate, tblThree.EndDate,
tblOne.ServiceYear, tblFive.ServiceBegin,
tblFive.ServiceEnd
FROM ((tblTwo INNER JOIN tblFour
ON tblTwo.AccountNbr=tblFour.AccountNbr) INNER JOIN (tblThree INNER JOIN tblOne
ON tblThree.ServiceID=tblOne.ServiceID)
ON tblFour.ClientID=tblOne.ClientID) INNER JOIN tblFive
ON tblOne.ContractID=tblFive.ContractID
WHERE tblThree.EndDate > tblFive.ServiceEnd;
SELECT
tblOne.ServiceID,
tblOne.ServiceYear,
tblOne.Status,
tblTwo.AccountNbr,
tblTwo.AcctName,
tblThree.BeginDate,
tblThree.EndDate,
tblFour.ClientID,
tblFour.ServiceName,
tblFive.ContractID,
tblFive.ServiceBegin,
tblFive.ServiceEnd
FROM tblOne
INNER JOIN tblThree
ON tblOne.ServiceID = tblThree.ServiceID
INNER JOIN tblFive
ON tblOne.ContractID = tblFive.ContractID
INNER JOIN tblFour
ON tblOne.ClientID = tblFour.ClientID
INNER JOIN tblTwo
ON tblTwo.AccountNbr = tblFour.Account
WHERE tblThree.EndDate > tblFive.ServiceEnd

How can i do this SQL in Linq? (Left outer join w/ dates)

My LINQ isnt the best, neither is my SQL but im trying to do something like this in LINQ (its kind of in pseudo-code)
select * from CarePlan c
-- only newest Referral based on r.Date (if more than one exists)
left outer join Referral r on r.CarePlanId = c.CarePlanId
where c.PatientId = 'E4A1DA8B-F74D-4417-8AC7-B466E3B3FFD0'
The data looks like this:
A Patient can have a bunch of careplans
each careplan can have 0 to n referrals (I want the newest referral per careplan - if any exist)
Would like to return a list of careplans for each patient (whether or not they have a referral or not, if it has more than one referral - grab the newest one)
Thanks for any help guys
In LINQ you use the DefaultIfEmpty to achieve a left outer join - examples at http://msdn.microsoft.com/en-us/library/bb397895.aspx
Assuming that the referrals are not a (potentially empty) collection on the care plans so you're joining two collections together ...
Your query it would be something like:
Get the latest referral per Care Plan:
var latestReferrals = from r in referrals
group r by r.CarePlanId into lr
select new { CarePlanId = lr.Key, LatestReferral = lr.OrderByDescending(lrd => lrd.Date).First()};
Find the combined details:
var q = from c in CarePlan
where c.PatientId = 'E4A1DA8B-F74D-4417-8AC7-B466E3B3FFD0'
join lr in latestReferrals on c.CarePlanId equals lr.CarePlanId into gj
from subReferral in gj.DefaultIfEmpty()
select new { CarePlanId = c.CarePlanId, LatestReferral = (subReferral == null) ? null : subReferral.LatestReferral };
Depending on whether you want many referral properties or just a few you may or may not want the whole Referral object in the second part or just extract the relevant properties.
You may be able to combine these into a single query but for readability it may be easier to keep them separate. If there is a combined solution you should also compare performance of the two approaches.
EDIT: see comment for joining patients/other tables from care plans
If Patient is joined from Referral (as per comment) then its more complex because you're doing several left outer joins. So switching to the slightly more concise syntax:
var combined = from c in carePlans
where c.PatientId = 'E4A1DA8B-F74D-4417-8AC7-B466E3B3FFD0'
from lr in latestReferral.Where(r => r.CarePlanId == c.CarePlanId).DefaultIfEmpty()
from p in patients.Where(patient => patient.PatientId == ((lr != null) ? lr.LatestReferral.PatientId : -1)).DefaultIfEmpty()
select new { c.CarePlanId, PatientName = (p == null) ? "no patient" : p.PatientName, LatestReferral = (lr == null) ? null : lr.LatestReferral };