How to a NHibernate subquery in Where clause with LINQ? - linq

I'm trying to write a correlated subquery in the where clause like this:
var foo = from d in session.Query<Document>()
where true ==
( from a in session.Query<ACLEntry>()
where a.Id == d.Id || a.Id == null
select a.Result
).FirstOrDefault()
select d;
The expected SQL output is very similar to this unanswered question on SO.
I think the Linq statement itself is fine because I can get it to run in LinqPad where I was prototyping. But NHibernate throws me these mysterious errors:
ERROR NHibernate.Hql.Parser [(null)] - NoViableAltException(86#[])
ERROR NHibernate.Hql.Parser [(null)] - MismatchedTreeNodeException(72!=3)
Is this an unsupported scenario with the NHibernate LINQ provider? Any ideas on how I might be able to restructure this query to get around it?

Try this instead :
var foo = from d in session.Query<Document>()
where (from a in session.Query<ACLEntry>()
where a.Id == d.Id || a.Id == null
select a.Result
).FirstOrDefault() != null
select d;
Hope this will help !!

It is probably having some trouble parsing the true == ... portion of the query.
Might want to try this instead,
var foo = from d in session.Query<Document>()
where (from a in session.Query<ACLEntry>()
where a.Id == d.Id || a.Id == null
select a.Result
).FirstOrDefault()
select d;

Related

SQL to LINQ with JOIN and SubQuery

I have a query that I' struggling to convert to LINQ. I just can't get my head around the required nesting. Here's the query in SQL (just freehand typed):
SELECT V.* FROM V
INNER JOIN VE ON V.ID = VE.V_ID
WHERE VE.USER_ID != #USER_ID
AND V.MAX > (SELECT COUNT(ID) FROM VE
WHERE VE.V_ID = V.ID AND VE.STATUS = 'SELECTED')
The Closest I've come to is this:
var query = from vac in _database.Vacancies
join e in _database.VacancyEngagements
on vac.Id equals e.VacancyId into va
from v in va.DefaultIfEmpty()
where vac.MaxRecruiters > (from ve in _database.VacancyEngagements
where ve.VacancyId == v.Id && ve.Status == Enums.VacanyEngagementStatus.ENGAGED
select ve).Count()
...which correctly resolves the subquery from my SQL statement. But I want to further restrict the returned V rows to only those where the current user does not have a related VE row.
I've realised that the SQL in the question was misleading and whilst it led to technically correct answers, they weren't what I was after. That's my fault for not reviewing the SQL properly so I apologise to #Andy B and #Ivan Stoev for the misleading post. Here's the LINQ that solved the problem for me. As stated in the post I needed to show vacancy rows where no linked vacancyEngagement rows existed. The ! operator provides ability to specify this with a subquery.
var query = from vac in _database.Vacancies
where !_database.VacancyEngagements.Any(ve => (ve.VacancyId == vac.Id && ve.UserId == user.Id))
&& vac.MaxRecruiters > (from ve in _database.VacancyEngagements
where ve.VacancyId == vac.Id && ve.Status == Enums.VacanyEngagementStatus.ENGAGED
select ve).Count()
This should work:
var filterOutUser = <userId you want to filter out>;
var query = from vac in _database.Vacancies
join e in _database.VacancyEngagements
on vac.Id equals e.VacancyId
where (e.UserId != filterOutUser) && vac.MaxRecruiters > (from ve in _database.VacancyEngagements
where ve.VacancyId == vac.Id && ve.Status == Enums.VacanyEngagementStatus.ENGAGED
select ve).Count()
select vac;
I removed the join to VacancyEngagements but if you need columns from that table you can add it back in.

Linq left outer join with multiple condition

I am new to Linq. I am trying to query some data in MS SQL.
Here is my statement:
select * from booking
left outer join carpark
on booking.bookingId = carpark.bookingId
where userID = 5 and status = 'CL'
When I run this in MS SQL, I get the expected result. How can I do this in Linq?
Thank you for your help.
you need this:
var query = (from t1 in tb1
join t2 in tb2 on t1.pKey = t2.tb1pKey into JoinedList
from t2 in JoinedList.DefaultIfEmpty()
where t1.userID == 5 && t1.status == "CL"
select new
{
t1,
t2
})
.ToList();
You can try to do left join this way :
from t1 in tb1
from t2 in tb2.Where(o => o.tb1pKey == t1.pKey).DefaultIfEmpty()
where tb1.userId == 5 && tb1.status == "CL"
select t1;
Usually when people say they want a "left outer join," that's just because they've already converted what they really want into SQL in their head. Usually what they really want is all of the items from table A, and the ability to get the related items from table B if there are any.
Assuming you have your navigation properties set up correctly, this could be as easy as:
var tb1sWithTb2s = context.tb1
.Include(t => t.tb2s) // Include all the tb2 items for each of these.
.Where(t => t.userID == 5 and t.status = "CL");

LINQ: A query body must end with a select clause or a group clause and other errors

I have the following SQL statement:
CASE
WHEN wt.pmtlr_oi IS NULL OR (SELECT COUNT(*) FROM mc.SCHEDENTRY WITH (NOLOCK) WHERE wt_oi = wt.wtskoi AND shedref_oi NOT IN (SELECT shdoi FROM mc.SCHDULE WITH (NOLOCK) WHERE aenm LIKE '%Breakin%')) = 0 AND wt.pmtlr_oi IS NULL
THEN 'Break-In'
ELSE 'Planned'
END AS schedule
which I have translated into:
Schedule = wt.pmtlr_oi == null || (from sch in SCHEDENTRies where wt_oi == wt.wtskoi && shedref_oi !(from sc in SCHDULEs
where sc.Aenm.Contains("Breakin") select sc.Shdoi)).Count() == 0 && wt.pmtlr_oi == null ? "Break-In" : "Planned"}
Here's how it looks in the select statement:
select new {Schedule = wt.pmtlr_oi == null || (from sch in SCHEDENTRies where wt_oi == wt.wtskoi && shedref_oi !(from sc in SCHDULEs
where sc.Aenm.Contains("Breakin") select sc.Shdoi)).Count() == 0 && wt.pmtlr_oi == null ? "Break-In" : "Planned"});
However when I try and run it there are some problems which I do not know how to fix. The first one is that the compiler doesn't appear to like the NOT IN found here:
&& shedref_oi !(from sc in SCHDULEs
I get a "A query body must end with a select clause or a group clause" error.
The compiler also doesn't like this:
select sc.Shdoi)).Count() == 0
On the outer parenthesis I get a "Syntax error ',' expected" error and on the period I get a "Statement expected" error message.
I would appreciate some help in troubleshooting this.
EDIT:
OK, After the comments I have corrected the LINQ statement to look like this:
select new {Schedule = wt.pmtlr_oi == null || (from sch in SCHEDENTRies where wt_oi == wt.wtskoi && !(from sc in SCHDULEs
where sc.Aenm.Contains("Breakin") select sc.Shdoi).Contains(shedref_oi)).Count() == 0 && wt.pmtlr_oi == null ? "Break-In" : "Planned"});
and the compiler likes it. However, it still doesn't like the .Count(). I get a "Statement expected" error. Am I incorrect in using .Count() for the sql SELECT COUNT(*)?

Linq query Left Join condition

I'm trying to recreate the following sql query using Linq syntax, for some reason it is not working, please let me know what am I doing wrong here
My sql query:
select
cf.VisitConfigId,
cf.VisitName,
sv.VisitDate
from SubjectVisitConfig cf
left join SubjectVisit sv on cf.VisitConfigId = sv.VisitConfigId
My Linq query:
var q = from cf in ctms.SubjectVisitConfigs
join sv in ctms.SubjectVisits on cf.VisitConfigId equals
sv.VisitConfigId into JoinedVisits
from sv in JoinedVisits.DefaultIfEmpty()
where sv.SubjectId == subjectId.Value && sv.SiteId == siteId.Value
select new
{
sv.VisitId,
VisitDate = sv.VisitDate != null ? sv.VisitDate : null,
cf.VisitName
};
Thanks for your help!
You're dereferencing sv unconditionally in your select clause - but sv will be logically null for items which don't have a matching SubjectVisit. How would you expect your where clause to match any result where sv is null?
Here's one possible rewrite:
var q = from cf in ctms.SubjectVisitConfigs
join sv in ctms.SubjectVisits
.Where(x => x.SubjectId == subjectId.Value &&
x.SiteId == siteId.Value)
on cf.VisitConfigId equals sv.VisitConfigId into JoinedVisits
from sv in JoinedVisits.DefaultIfEmpty()
select new
{
VisitId = sv == null ? null : sv.VisitId,
VisitDate = sv == null ? null : sv.VisitDate,
cf.VisitName
};

Convert SQL query to LINQ

The below is my SQL query and want to be in LINQ. Can anybody help for this?
SELECT EmpId,Team,_Year FROM Plan
where EmpId in
(
select EmpId from master where 2150 in (immediatesupervisor,manager)
)
I suggest you to use join operation like this
YourDbEntities db = new YourDbEntities();
var query = from c in db.Plan
join d in db.master on c.EmpId equals d.EmpId
where d.ImmediateSupervisor == 2150 || d.Manager == 2150
select new{
c.EmpId,
c.Team,
c._Year
};
Try:
var q =
from p in dc.Plan
where (
from m in dc.Master
where m.ImmediateSupervisor == 2150
|| m.Manager == 2150
select m.EmpId
).Contains(p.EmpId)
select new { p.EmpId, p.Team, p._Year };
A great resource for commonly used linq syntax is Damien Guard's Linq-to-SQL 'cheat sheet'. It is a one-pager where you can quickly look up things like this. See http://damieng.com/blog/2009/08/12/linq-to-sql-cheat-sheet

Resources