LINQ to NHibernate WHERE EXISTS IN - nhibernate

I've been trying out NHibernate 3 and LINQ to NHibernate. I can't get it to spit out the correct T-SQL query.
Here's my domain model:
Employee { id, name }
Department { id, name }
EmployeeDepartment { id, employee_id, department_id, startdate, enddate }
AttendanceRegistration { id, datetime, employee_id }
Now suppose I'd like to select all AttendanceRegistrations between '2010-10-1' and '2010-11-1' that were connected to a certain department at that time.
DateTime start = new DateTime(2010,10,1);
DateTime end = new DateTime(2010,11,1);
var list =
from ar in session.Query<AttendanceRegistration>()
where
start <= ar.datetime && ar.datetime > end && (
from ed in session.Query<EmployeeDepartment>()
where
ed.startdate <= ar.datetime && ed.enddate > ar.datetime &&
ed.department_id = 1
select ed.employee_id
).Contains(ar.employee_id)
select ar;
The resulting SQL Code will look like this:
select ar.id, ar.datetime, ar.employee_id
from AttendanceRegistration ar
where
'2010-10-1 00:00:00' <= ar.datetime and '2010-11-1' > ar.datetime and exists (
select ed.employee_id
from EmployeeDepartment ed
where
ed.department_id=1 and
ed.startdate <= ar.datetime and
ed.enddate > ar.datetime and
ed.id=ar.employee_id
)
This is ALMOST good :-) The only mistake is
ed.id=ar.employee_id
This should have been:
ed.employee_id=ar.employee_id
Does anybody have ideas how to get LINQ to NHibernate spit out the correct T-SQL query?

I ran into the same problem. I found a way to get around this. Your query can be rewritten as follows. Basically instead of using Contains() operator, add your predicate explicitly in the where clause and use Any() operator.
DateTime start = new DateTime(2010,10,1);
DateTime end = new DateTime(2010,11,1);
var list =
from ar in session.Query<AttendanceRegistration>()
where
start <= ar.datetime && ar.datetime > end && (
from ed in session.Query<EmployeeDepartment>()
where
ed.startdate <= ar.datetime && ed.enddate > ar.datetime &&
ed.department_id == 1
&& ed.employee_id == ar.employee_id
select ed
).Any()
select ar;

Related

join, group by and count sql to linq conversion

Query:
SELECT COUNT(*) as Avalied
FROM LeaveMaster as lm
JOIN LeaveSubsidary as ls
ON lm.TransMasterId = ls.TransMasterId
WHERE lm.SystemCode = 'abc123' AND lm.EmployeeCode = '0014' AND lm.Status ='Approved'
Group by ls.Leave_Type
How would you convert the above sql query to linq? Thanks :)
Edit :
from p in db.PY_LeaveTransactionMasterTAB.AsEnumerable()
join e in db.PY_LeaveTransactionSubsidaryTAB.AsEnumerable() on p.LV_TransMasterId equals e.LV_TransMasterId into grp
where p.SystemCode == SysCode && p.EmployeeCode == EmpCode && p.Status == "Approved"
group grp by e.Leave_Type // This line is invalid Why?
The above is what I have tried so far, why can't I do e.Leave_Type or what is the right way to do group grp by e.Leave_Type?
You could try this:
(from p in db.PY_LeaveTransactionMasterTAB
join e in db.PY_LeaveTransactionSubsidaryTAB on p.LV_TransMasterId equals e.LV_TransMasterId
where p.SystemCode == SysCode && p.EmployeeCode == EmpCode && p.Status == "Approved"
group new {p,e} by new {e.Leave_Type } into gr
select new
{
Leave_Type = gr.Key.Leave_Type ,
Count = gr.Count()
}).ToList();

Linq union all equivalent of sql code

I have the following queries:
var majorClients = maj in dbContext.MajorClients
where (maj.startdate > startDate)
where (maj.status == "Active")
Select new Client{EntityPK = maj.mjPrimaryKey,Name = maj.name, Type = "Maj"};
var minorClients = min in dbContext.MinorClients
where (min.startdate > startDate)
where (min.status == "Active" || min.status== "Inactive")
Select new Client{EntityPK = min.mnPrimaryKey,Name = min.name, Type = "Min"};
There are clients that could appear in both major and minor tables. I would like to return a list of all occurrences of clients in both tables, however if there are matching clients by name, then I would only want to return the matching record from the majorClients table.
I have written a sql query to return the results:
SELECT mjPrimaryKey AS EntityPK,name,'Maj' AS TYPE
FROM majorClients
WHERE status = 'Active' AND startDate > #startDate
UNION ALL
SELECT mnPrimaryKey,name,'Min' FROM minorClients
WHERE status IN ('Active','Inactive') AND startDate > #startDate
WHERE name NOT IN (SELECT name FROM majorClients WHERE status = 'Active' AND startDate > #startDate)
How would I represent this query in linq?
Try this linq. To exclude duplicates from minorClients, I've used Contains method. To union all objects - Union method:
var majorClients = from maj in dbContext.MajorClients
where maj.startdate > startDate
&& maj.status == "Active"
select new Client
{
EntityPK = maj.mjPrimaryKey,
Name = maj.name,
Type = "Maj"
};
var minorClients = from min in dbContext.MinorClients
where min.startdate > startDate
&& min.status == "Active" || min.status== "Inactive"
&& !(from maj in dbContext.MajorClients
where maj.startdate > startDate
&& maj.status == "Active"
select maj.name).Contains(min.Name)
select new Client
{
EntityPK = min.mnPrimaryKey,
Name = min.name,
Type = "Min"
};
var allClients = majorClients.Union(minorClients);

SQL to Entity Framework query for distinct instances

I need to translate the following query from SQL into an Entity Framework query. Can anyone please help.
var query3 = string.Format(#"
SELECT DISTINCT
Boxes.BoxName,
Employees.EmployeeNumber,
Boxes.Port,
Boxes.SerialNumber
FROM
Eventlog
INNER JOIN Boxes
ON Eventlog.SerialNumber = Boxes.SerialNumber
INNER JOIN Employees
ON Eventlog.EmployeeId = Employees.EmployeeId
WHERE
ActionId = {4}
AND Boxes.Deactivated = 0
AND ( ('*' = '{0}')
OR (Boxes.SerialNumber = '{0}') )
AND ( (-1 = {1})
OR (Employees.EmployeeId = '{1}') )
AND EventTime >= '{2}'
AND EventTime <= '{3}'
", boxFilter3, ReportEmployeeIdFilter, ReportStartDate, ReportEndDate, actionFilter);
Something like this should work:
var query = (from log in context.Eventlog
join box in context.Boxes
on log.SerialNumber equals box.SerialNumber
join employee in context.Employees
on log.EmployeeId equals employee.EmployeeId
where log.ActionId == actionFilter
&& box.Deactivated == 0
&& (boxFilter3 == "*" || box.SerialNumber == boxFilter3)
&& (ReportEmployeeIdFilter == -1 || employee.EmployeeId == ReportEmployeeIdFilter)
&& log.EventTime >= ReportStartDate
&& log.EventTime <= ReportEndDate
select new
{
box.BoxName,
employee.EmployeeNumber,
box.Port,
box.SerialNumber
})
.Distinct();

Linq to SQL combination of aggregate functions

Is there a way to simplify this and make it go faster?
In SQL I use count(*) and count(distinct) in same query which gives me a faster result
Thanks a bunch.
int numberOfUsers = (from u in db.UseLogs
where u.DocID == docID
&& u.LogDate >= fromDate
&& u.LogDate <= to
select u.UserID).Distinct().Count();
int numberOfVisits = (from u in db.UseLogs
where u.DocID == docID
&& u.LogDate >= fromDate
&& u.LogDate <= to
select u).Count();
Conclusion
There is no Count( Distinct) in LINQ. Not EVERY SQL statement can be translated into LINQ.
Thanks for the help guys!
Is this what you're looking for?
from u in db.UseLogs
where u.DocId == docId && u.LogDate >= fromDate && u.LogDate <= to
group u by true into g
select new
{
Count = g.Count(),
DistinctUserCount = g.Select(x => x.UserId).Distinct().Count()
}
You will want to check if it's actually faster than running two queries, or if the performance gain is worth the loss of readability.
Not exactly what you're trying to acheive but may be just as fast:
var query =
from u in db.UseLogs
where u.DocId == docId && u.LogDate >= fromDate && u.LogDate <= to
group u by u.UserID into g
select new
{
Visits = g.Count()
};
int numberOfUsers = query.Count();
int numberOfVisits = query.Sum(q=>q.Visits);
It executes the SQL only once and does the SUMming in memory.

Linq 2 SQL Syntax Help

I am almost done converting a MySQL app to Linq2SQL but struggling to get my head round this last SQL query
SELECT a.URL, b.URL AS DuplicateURL
FROM Pages a
INNER JOIN Pages b ON a.MetaDescription = b.MetaDescription
AND a.PageID <> b.PageID
WHERE a.DomainID = #reportid
AND b.DomainID = #reportid
AND LENGTH(TRIM(a.MetaDescription)) > 0
AND a.URL < b.URL
ORDER BY a.URL ASC
Could anymore give me some syntax help on how I would create this query in Linq2SQL?
Any help greatly appreciated
It goes like this:
var DuplicatePages =
from a in DBContext.Pages
join b in DBContext.Pages on a.MetaDescription equals b.MetaDescription
where (a.PageID <> b.PageID) && (a.DomainID == ReportID) &&
(b.DomainID == ReportID) && (a.MetaDescription.Trim().Length > 0) &&
(a.URL < b.URL)
orderby a.URL
select new { Url = a.URL, DuplicateUrl = b.URL };
That's pretty straigtforward:
var reportId = ...;
var duplicates =
from a in db.Pages
from b in db.Pages
where a.MetaDescription == b.MetaDescription
where a.PageID != b.PageID
where a.DomainID == reportId
where b.DomainID == reportId
where a.MetaDescription.Trim().Length > 0
where a.URL < b.URL
orderby a.URL
select new { Url = a.URL, DuplicateUrl = b.Url }