What's wrong with this LINQ? - c#

I am using LINQ TO Entities & need to use Union operator.
This is my raw sql query.
(select DISTINCT c.DocumentId from [sDocument].[tDocumentStatus] c
inner join [sDocument].[tTOCStructure] d on c.DocumentId = d.FolderID
inner join [sDocument].[tAudit] e on c.DocumentId = e.FolderID
where d.FolderType = 2 and d.isDeleted = 0 and d.ClientID = 9 and e.AuditDescriptionID != 10)
Union
(select DISTINCT c.FolderID from [sDocument].[tTOCStructure] c
inner join [sDocument].[tAudit] e on c.DocumentId = e.FolderID
where c.FolderType = 2 and c.isDeleted = 0 and c.ClientID = 9 )
When I run the above sql, I get around 45 records. That's right as well
Below is LINQ for the same requirement.
IQueryable<DocumentListMapper> query = (
from c in entities.tDocumentStatus
join d in entities.tTOCStructures on c.DocumentId equals d.FolderID
join e in entities.tAudits on c.DocumentId equals e.FolderID
where d.FolderType == 2 && d.isDeleted == false && d.ClientID == clientId && e.AuditDescriptionID != 10
select new DocumentListMapper()
{
DocumentId = c.DocumentId,
DocumentName = d.CheckoutFolderName,
PublishDate = c.AssignedDate
}).Distinct().Union(
from c in entities.tTOCStructures
join e in entities.tAudits on c.FolderID equals e.FolderID
where c.FolderType == 2 && c.isDeleted == false && c.ClientID == clientId
select new DocumentListMapper()
{
DocumentId = c.FolderID,
DocumentName = c.CheckoutFolderName,
PublishDate = e.TaskDateTime
}).Distinct().OrderBy(x => x.PublishDate).Skip(pager * 50).Take(50);
But this LINQ returns more than 2500 records. This is not the desired records.
What's wrong in my LINQ??

Related

Join multiple columns from the same table using Linq

I would like to convert following sql query into Linq to SQL
select distinct r.CompanyLogo, j.JobName, j.JobId, ur.UserId, r.JobSeekerID
, ur.FirstName, j.JobType, j.JobCareerLevel, j.JobLocation
from UserInterest m
join job j on m.FunctionalId = j.FunctionId or m.Careerlevel = j.CarrerLevelId or m.SalId = j.SalaryRangeId
join UserRegistration ur on j.UserId = ur.UserId
join EmplrRegistration r on j.UserId = r.JobSeekerID
where m.Status = 1 and m.UserId = 1
going through this I have so far tried following which didn't work out
var list = (from m in entities.UserInterests
from j in entities.Jobs
where m.FunctionalId == j.FunctionId || m.SalId == j.SalaryRangeId || m.Careerlevel == j.CarrerLevelId
&& m.Status == true && m.UserId == 1
join ur in entities.UserRegistrations on m.UserId equals ur.UserId
join r in entities.EmplrRegistrations on m.UserId equals r.JobSeekerID
select new { r.CompanyLogo, j.JobName, j.JobId, ur.UserId, r.JobSeekerID
, ur.FirstName, j.JobType, j.JobCareerLevel, j.JobLocation }).Distinct().ToList();
Edit:
following query is being generated against Svyatoslav Danyliv answer which is returning 7 rows instead of 6
SELECT 1 AS [C1], [Extent4].[CompanyLogo] AS [CompanyLogo], [Extent2].[JobName] AS [JobName]
,[Extent2].[JobId] AS [JobId], [Extent3].[UserId] AS [UserId]
,[Extent4].[JobSeekerID] AS [JobSeekerID], [Extent3].[FirstName] AS [FirstName]
,[Extent2].[JobType] AS [JobType], [Extent2].[JobCareerLevel] AS [JobCareerLevel]
,[Extent2].[JobLocation] AS [JobLocation]
FROM [dbo].[UserInterest] AS [Extent1]
INNER JOIN [dbo].[Job] AS [Extent2] ON ([Extent1].[FunctionalId] = [Extent2].[FunctionId])
OR (([Extent1].[FunctionalId] IS NULL) AND ([Extent2].[FunctionId] IS NULL))
OR ([Extent1].[Careerlevel] = [Extent2].[CarrerLevelId])
OR (([Extent1].[Careerlevel] IS NULL) AND ([Extent2].[CarrerLevelId] IS NULL))
OR ([Extent1].[SalId] = [Extent2].[SalaryRangeId])
OR (([Extent1].[SalId] IS NULL)
AND ([Extent2].[SalaryRangeId] IS NULL))
INNER JOIN [dbo].[UserRegistration] AS [Extent3] ON [Extent2].[UserId] = [Extent3].[UserId]
INNER JOIN [dbo].[EmplrRegistration] AS [Extent4] ON [Extent2].[UserId] = [Extent4].[JobSeekerID]
WHERE (1 = [Extent1].[Status]) AND (1 = [Extent1].[UserId])
Join which contains not just AND expressions is possible via from x in entities.Where(x => ..). You have did that partially and made mistake in where condition.
Corrected query, looks the same as original SQL
var query =
from m in entities.UserInterests
from j in entities.Jobs.Where(j =>
m.FunctionalId != null && m.FunctionalId == j.FunctionId ||
m.Careerlevel != null && m.Careerlevel == j.CarrerLevelId ||
m.SalId != null && m.SalId == j.SalaryRangeId)
join ur in entities.UserRegistrations on j.UserId equals ur.UserId
join r in entities.EmplrRegistrations on j.UserId equals r.JobSeekerID
where m.Status == true && m.UserId == 1
select new { r.CompanyLogo, j.JobName, j.JobId, ur.UserId, r.JobSeekerID
, ur.FirstName, j.JobType, j.JobCareerLevel, j.JobLocation };
var list = query.Distinct().ToList();

linq to sql make simple group by at the end

I have this linq
(from a in Customers
join b in CustomerContacts.Where(p => p.Contact.ContactType.Code == "phone") on a.Id equals b.CustomerId into bb
from b in bb.DefaultIfEmpty()
join e in CustomerContacts.Where(p => p.Contact.ContactType.Code == "email") on a.Id equals e.CustomerId into ee
from e in ee.DefaultIfEmpty()
join f in Bookings.Where(p => p.EntityId == 4) on a.Id equals f.CustomerId into ff
from f in ff.DefaultIfEmpty()
join h in CustomerAddresses on a.Id equals h.CustomerId into hh
from h in hh.DefaultIfEmpty()
where
(b.Contact.Value.Contains("123") || e.Contact.Value.Contains("123"))
&& (a.EntityId == 4 || f != null)
select new {
a.Id,
phone = b.Contact.Value,
email = e.Contact.Value,
count = Vehicles.Where(p => p.CustomerId == a.Id).Count(),
h.Address.State,
h.Address.Suburb
}
)
It translated to sql (mysql)
SELECT `a`.`Id`, `b.Contact`.`Value` AS `phone`, `e.Contact`.`Value` AS `email`, (
SELECT COUNT(*)
FROM `Vehicle` AS `p2`
WHERE `p2`.`CustomerId` = `a`.`Id`
) AS `count`, `h.Address`.`State`, `h.Address`.`Suburb`
FROM `Customer` AS `a`
LEFT JOIN (
SELECT `p`.*
FROM `CustomerContact` AS `p`
INNER JOIN `Contact` AS `p.Contact` ON `p`.`ContactId` = `p.Contact`.`Id`
INNER JOIN `ContactType` AS `p.Contact.ContactType` ON `p.Contact`.`ContactTypeId` = `p.Contact.ContactType`.`Id`
WHERE `p.Contact.ContactType`.`Code` = 'phone'
) AS `t` ON `a`.`Id` = `t`.`CustomerId`
LEFT JOIN `Contact` AS `b.Contact` ON `t`.`ContactId` = `b.Contact`.`Id`
LEFT JOIN (
SELECT `p0`.*
FROM `CustomerContact` AS `p0`
INNER JOIN `Contact` AS `p.Contact0` ON `p0`.`ContactId` = `p.Contact0`.`Id`
INNER JOIN `ContactType` AS `p.Contact.ContactType0` ON `p.Contact0`.`ContactTypeId` = `p.Contact.ContactType0`.`Id`
WHERE `p.Contact.ContactType0`.`Code` = 'email'
) AS `t0` ON `a`.`Id` = `t0`.`CustomerId`
LEFT JOIN `Contact` AS `e.Contact` ON `t0`.`ContactId` = `e.Contact`.`Id`
LEFT JOIN (
SELECT `p1`.*
FROM `Booking` AS `p1`
WHERE `p1`.`EntityId` = 4
) AS `t1` ON `a`.`Id` = `t1`.`CustomerId`
LEFT JOIN `CustomerAddress` AS `h` ON `a`.`Id` = `h`.`CustomerId`
LEFT JOIN `Address` AS `h.Address` ON `h`.`AddressId` = `h.Address`.`Id`
WHERE ((LOCATE('123', `b.Contact`.`Value`) > 0) OR (LOCATE('123', `e.Contact`.`Value`) > 0)) AND ((`a`.`EntityId` = 4) OR `t1`.`Id` IS NOT NULL)
and the result
however it contains duplicated Id, I want to add group by a.Id at the end to remove duplicated Id. Tried with group by but it cannot achieve some thing like this
SELECT `a`.`Id`, `b.Contact`.`Value` AS `phone`, `e.Contact`.`Value` AS `email`, (
SELECT COUNT(*)
FROM `Vehicle` AS `p2`
WHERE `p2`.`CustomerId` = `a`.`Id`
) AS `count`, `h.Address`.`State`, `h.Address`.`Suburb`
FROM `Customer` AS `a`
LEFT JOIN (
SELECT `p`.*
FROM `CustomerContact` AS `p`
INNER JOIN `Contact` AS `p.Contact` ON `p`.`ContactId` = `p.Contact`.`Id`
INNER JOIN `ContactType` AS `p.Contact.ContactType` ON `p.Contact`.`ContactTypeId` = `p.Contact.ContactType`.`Id`
WHERE `p.Contact.ContactType`.`Code` = 'phone'
) AS `t` ON `a`.`Id` = `t`.`CustomerId`
LEFT JOIN `Contact` AS `b.Contact` ON `t`.`ContactId` = `b.Contact`.`Id`
LEFT JOIN (
SELECT `p0`.*
FROM `CustomerContact` AS `p0`
INNER JOIN `Contact` AS `p.Contact0` ON `p0`.`ContactId` = `p.Contact0`.`Id`
INNER JOIN `ContactType` AS `p.Contact.ContactType0` ON `p.Contact0`.`ContactTypeId` = `p.Contact.ContactType0`.`Id`
WHERE `p.Contact.ContactType0`.`Code` = 'email'
) AS `t0` ON `a`.`Id` = `t0`.`CustomerId`
LEFT JOIN `Contact` AS `e.Contact` ON `t0`.`ContactId` = `e.Contact`.`Id`
LEFT JOIN (
SELECT `p1`.*
FROM `Booking` AS `p1`
WHERE `p1`.`EntityId` = 4
) AS `t1` ON `a`.`Id` = `t1`.`CustomerId`
LEFT JOIN `CustomerAddress` AS `h` ON `a`.`Id` = `h`.`CustomerId`
LEFT JOIN `Address` AS `h.Address` ON `h`.`AddressId` = `h.Address`.`Id`
WHERE ((LOCATE('123', `b.Contact`.`Value`) > 0) OR (LOCATE('123', `e.Contact`.`Value`) > 0)) AND ((`a`.`EntityId` = 4) OR `t1`.`Id` IS NOT NULL)
Group by `a`.`Id`
Have you tried something like this?
(from a in Customers
join b in CustomerContacts.Where(p => p.Contact.ContactType.Code == "phone") on a.Id equals b.CustomerId into bb
from b in bb.DefaultIfEmpty()
join e in CustomerContacts.Where(p => p.Contact.ContactType.Code == "email") on a.Id equals e.CustomerId into ee
from e in ee.DefaultIfEmpty()
join f in Bookings.Where(p => p.EntityId == 4) on a.Id equals f.CustomerId into ff
from f in ff.DefaultIfEmpty()
join h in CustomerAddresses on a.Id equals h.CustomerId into hh
from h in hh.DefaultIfEmpty()
where
(b.Contact.Value.Contains("123") || e.Contact.Value.Contains("123"))
&& (a.EntityId == 4 || f != null)
select new {
a.Id,
phone = b.Contact.Value,
email = e.Contact.Value,
count = Vehicles.Where(p => p.CustomerId == a.Id).Count(),
h.Address.State,
h.Address.Suburb
}).GroupBy(i => i.Id).ToList();

entity framework multi column

In sqlcommand I have this:
SELECT *
FROM cliente c
LEFT JOIN abono a on
c.idcliente = a.idcliente
and (a.estatus = 1 or a.estatus = null)
LEFT JOIN usuario u on
a.creadopor = u.idusuario
WHERE c.estatus = 1
We know this is not the same than this:
SELECT *
FROM cliente c
LEFT JOIN abono a on
c.idcliente = a.idcliente
LEFT JOIN usuario u on
a.creadopor = u.idusuario
WHERE c.estatus=1
and (a.estatus = 1 or a.estatus = null)
How can I do the first query in entity framework?
the second query in entity framework is it
from c in Conexion.conexion.conect.cliente
join a in Conexion.conexion.conect.abono
on c.idcliente equals a.idcliente into alj
from a in alj.DefaultIfEmpty()
join u in Conexion.conexion.conect.usuario
on a.creadopor equals u.idusuario into ulj
from u in ulj.DefaultIfEmpty()
where c.estatus == 1
&& (a.estatus == 1 || a.estatus == null)
but i could not get the first query
This does the trick:
from c in Conexion.conexion.conect.cliente
join a in Conexion.conexion.conect.abono.Where(x.estatus == 1 || x.estatus == null)
on c.idcliente equals a.idcliente into alj
from a in alj.DefaultIfEmpty()
join u in Conexion.conexion.conect.usuario
on a.creadopor equals u.idusuario into ulj
from u in ulj.DefaultIfEmpty()
where c.estatus == 1

Getting Total Record by Group by in Linq

I have one query in SQL, want to convert it to Linq. My Query is :
select count(tbs.tbsid) as CNTSeats,tbm.BusNo
from tdp_tourpackageschedule tps
join tdp_tourpackage tp on tp.TourID = tps.FK_TourID
join tdp_tourbusseats tbs on tbs.tbsid = tps.fk_tbsid
join tdp_tourbusmaster tbm on tbm.tbid = tbs.fk_tbid
where fk_tdid = #FKTDID and fk_TourID = #FKTourID and IsOpen = 1
group by tbm.BusNo
I tried this Code:
var tourAvail = (from ts in entities.tdp_TourPackageSchedule
join tp in entities.tdp_TourPackage on ts.FK_TourID equals tp.TourID
join tbs in entities.tdp_TourBusSeats on ts.FK_TBSID equals tbs.TBSID
join tb in entities.tdp_TourBusMaster on tbs.FK_TBID equals tb.TBID
where ts.FK_TDID == TDID && ts.FK_TourID == TourID && ts.IsOpen == 1
group tb by tb.BusNo into cnt
select new
{
//BusNo = cnt.bu
//Count = cnt.Select(x => x.tdp_TourBusSeats).Distinct().Count()
});
I don't know how to get count of records, anyone can help ?
Do :
var tourAvail = (from ts in entities.tdp_TourPackageSchedule
join tp in entities.tdp_TourPackage on ts.FK_TourID equals tp.TourID
join tbs in entities.tdp_TourBusSeats on ts.FK_TBSID equals tbs.TBSID
join tb in entities.tdp_TourBusMaster on tbs.FK_TBID equals tb.TBID
where ts.FK_TDID == TDID && ts.FK_TourID == TourID && ts.IsOpen == 1
group tb by tb.BusNo into cnt
select new
{
BusNo = cnt.Key,
Count = cnt.Count()
}).ToList();

why does LINQ To SQL result in SQL like this?

When LINQ translates the below syntax to SQL, the (inner) where clause gets moved to the outer-most query. That's super-unfriendly to the database. I wrote this like Hibernate's HQL (is this appropriate?), and I've written SQL for many moons.
Can anyone help explain what gives, or point me in the way of a resolution?
var rc = (
from dv in (
from dv_j in (
from x in adc.JobManagement
join j in adc.Job on x.JobId equals j.JobId
join js in adc.JobStatus on j.StatusId equals js.JobStatusId
join cm in adc.ClientManagement on j.ClientId equals cm.ClientId
join o in adc.User on cm.UserId equals o.UserId
join jm in adc.JobManagement on j.JobId equals jm.JobId
where
(x.UserId == aid || cm.UserId == aid)
&& (j.StatusDate == null || j.StatusDate >= getFromDate())
&& (jm.ManagementRoleCode == MR_MANAGER)
select new
{
j.JobId,
Job = j.InternalName == null ? j.ExternalName : j.InternalName,
JobStatusDate = j.StatusDate,
JobStatus = js.Code,
Owner = o.Username,
Role = jm.ManagementRoleCode
})
join s in adc.Submission on dv_j.JobId equals s.JobId into dv_s
from s in dv_s.DefaultIfEmpty()
select new
{
dv_j.JobId,
dv_j.Job,
dv_j.JobStatusDate,
dv_j.JobStatus,
dv_j.Owner,
dv_j.Role,
s.SubmissionId,
s.CandidateId,
s.SubmissionDate,
StatusDate = s.StatusDate,
StatusId = s.StatusId
})
join c in adc.Candidate on dv.CandidateId equals c.CandidateId into dv_c
join ss in adc.SubmissionStatus on dv.StatusId equals ss.SubmissionStatusId into dv_ss
from c in dv_c.DefaultIfEmpty()
from ss in dv_ss.DefaultIfEmpty()
orderby
dv.StatusId == null ? dv.StatusDate : dv.JobStatusDate descending,
dv.Job,
c.LastName,
c.NickName,
c.FirstName
select new Projects
{
Id = dv.JobId,
Project = dv.Job,
Submitted = dv.SubmissionDate,
Candidate = FormatIndividual(c.LastName, c.FirstName, c.NickName),
Status = dv.StatusId == null ? ss.Code : dv.JobStatus,
StatusDate = dv.StatusId == null ? dv.StatusDate : dv.JobStatusDate,
Role = dv.Role,
Owner = dv.Owner
});
Try breaking down the one statement into two. This would work as it cannot move the where to a place that doesn't exist yet. This does make multiple round trips to the database, but it is better than having most of several large tables being joined then culled. I would try this:
var inMemoryTable = (
from x in adc.JobManagement
join j in adc.Job on x.JobId equals j.JobId
join js in adc.JobStatus on j.StatusId equals js.JobStatusId
join cm in adc.ClientManagement on j.ClientId equals cm.ClientId
join o in adc.User on cm.UserId equals o.UserId
join jm in adc.JobManagement on j.JobId equals jm.JobId
where
(x.UserId == aid || cm.UserId == aid)
&& (j.StatusDate == null || j.StatusDate >= getFromDate())
&& (jm.ManagementRoleCode == MR_MANAGER)
select new
{
j.JobId,
Job = j.InternalName == null ? j.ExternalName : j.InternalName,
JobStatusDate = j.StatusDate,
JobStatus = js.Code,
Owner = o.Username,
Role = jm.ManagementRoleCode
});
var rc = (
from dv in (
from dv_j in inMemoryTable
join s in adc.Submission on dv_j.JobId equals s.JobId into dv_s
from s in dv_s.DefaultIfEmpty()
select new
{
dv_j.JobId,
dv_j.Job,
dv_j.JobStatusDate,
dv_j.JobStatus,
dv_j.Owner,
dv_j.Role,
s.SubmissionId,
s.CandidateId,
s.SubmissionDate,
StatusDate = s.StatusDate,
StatusId = s.StatusId
})
join c in adc.Candidate on dv.CandidateId equals c.CandidateId into dv_c
join ss in adc.SubmissionStatus on dv.StatusId equals ss.SubmissionStatusId into dv_ss
from c in dv_c.DefaultIfEmpty()
from ss in dv_ss.DefaultIfEmpty()
orderby
dv.StatusId == null ? dv.StatusDate : dv.JobStatusDate descending,
dv.Job,
c.LastName,
c.NickName,
c.FirstName
select new Projects
{
Id = dv.JobId,
Project = dv.Job,
Submitted = dv.SubmissionDate,
Candidate = FormatIndividual(c.LastName, c.FirstName, c.NickName),
Status = dv.StatusId == null ? ss.Code : dv.JobStatus,
StatusDate = dv.StatusId == null ? dv.StatusDate : dv.JobStatusDate,
Role = dv.Role,
Owner = dv.Owner
});

Categories

Resources