Linq To Entities Generating Big Queries - linq

I've been running a trace on some of the queries Linq is generating and they seem very unoptimized and clumsy.
I realise you dont know my data structure but is tere anything immidiatly wrong with the following linq query
IQueryable<Tasks> tl = db.Tasks
.Include("Catagories")
.Include("Projects")
.Include("TaskStatuses")
.Include("AssignedTo")
.Where
(t => (t.TaskStatuses.TaskStatusId.Equals(currentStatus) | currentStatus == -1) &
(t.Projects.ProjectId.Equals(projectId) | projectId == -1) &
(t.Subject.Contains(SearchText) | t.Description.Contains(SearchText) | SearchText == "" | SearchText == null) &
(t.Projects.Active == true) &
(t.Catagories.Active == true || t.Catagories==null) &
(t.LoggedBy.UserProfile.Companies.CompanyId == CompanyId) &
(assignedToGuid == rnd | t.AssignedTo.UserId.Equals(assignedToGuid))).OrderBy(SortField + " " + SortOrder);
When it runs it generates this SQL query
exec sp_executesql N'SELECT
[Project1].[C1] AS [C1],
[Project1].[TaskId] AS [TaskId],
[Project1].[Subject] AS [Subject],
[Project1].[Description] AS [Description],
[Project1].[EstimateDays] AS [EstimateDays],
[Project1].[EstimateHours] AS [EstimateHours],
[Project1].[DateLogged] AS [DateLogged],
[Project1].[DateModified] AS [DateModified],
[Project1].[AssignedTo] AS [AssignedTo],
[Project1].[C2] AS [C2],
[Project1].[CatagoryId] AS [CatagoryId],
[Project1].[CatagoryName] AS [CatagoryName],
[Project1].[CreatedOn] AS [CreatedOn],
[Project1].[Active] AS [Active],
[Project1].[CreatedBy] AS [CreatedBy],
[Project1].[C3] AS [C3],
[Project1].[ProjectId] AS [ProjectId],
[Project1].[ProjectName] AS [ProjectName],
[Project1].[CreatedOn1] AS [CreatedOn1],
[Project1].[Active1] AS [Active1],
[Project1].[CreatedBy1] AS [CreatedBy1],
[Project1].[TaskStatusId] AS [TaskStatusId],
[Project1].[StatusName] AS [StatusName],
[Project1].[C4] AS [C4],
[Project1].[ApplicationId] AS [ApplicationId],
[Project1].[UserId] AS [UserId],
[Project1].[UserName] AS [UserName],
[Project1].[LoweredUserName] AS [LoweredUserName],
[Project1].[MobileAlias] AS [MobileAlias],
[Project1].[IsAnonymous] AS [IsAnonymous],
[Project1].[LastActivityDate] AS [LastActivityDate],
[Project1].[UserId1] AS [UserId1],
[Project1].[UserId2] AS [UserId2]
FROM ( SELECT
[Filter1].[TaskId] AS [TaskId],
[Filter1].[Subject] AS [Subject],
[Filter1].[Description] AS [Description],
[Filter1].[AssignedTo] AS [AssignedTo],
[Filter1].[EstimateDays] AS [EstimateDays],
[Filter1].[EstimateHours] AS [EstimateHours],
[Filter1].[DateLogged] AS [DateLogged],
[Filter1].[DateModified] AS [DateModified],
[Filter1].[CatagoryId1] AS [CatagoryId],
[Filter1].[CatagoryName] AS [CatagoryName],
[Filter1].[CreatedBy1] AS [CreatedBy],
[Filter1].[CreatedOn1] AS [CreatedOn],
[Filter1].[Active1] AS [Active],
[Filter1].[ProjectId1] AS [ProjectId],
[Filter1].[ProjectName1] AS [ProjectName],
[Filter1].[CreatedOn2] AS [CreatedOn1],
[Filter1].[Active2] AS [Active1],
[Filter1].[CreatedBy2] AS [CreatedBy1],
[Filter1].[TaskStatusId1] AS [TaskStatusId],
[Filter1].[StatusName] AS [StatusName],
[Filter1].[ApplicationId1] AS [ApplicationId],
[Filter1].[UserId1] AS [UserId],
[Filter1].[UserName1] AS [UserName],
[Filter1].[LoweredUserName1] AS [LoweredUserName],
[Filter1].[MobileAlias1] AS [MobileAlias],
[Filter1].[IsAnonymous1] AS [IsAnonymous],
[Filter1].[LastActivityDate1] AS [LastActivityDate],
[Filter1].[UserId2] AS [UserId1],
[Join12].[UserId3] AS [UserId2],
1 AS [C1],
1 AS [C2],
1 AS [C3],
1 AS [C4]
FROM (SELECT [Extent1].[TaskId] AS [TaskId], [Extent1].[Subject] AS [Subject], [Extent1].[Description] AS [Description], [Extent1].[ProjectId] AS [ProjectId2], [Extent1].[TaskStatusId] AS [TaskStatusId2], [Extent1].[LoggedBy] AS [LoggedBy], [Extent1].[AssignedTo] AS [AssignedTo], [Extent1].[EstimateDays] AS [EstimateDays], [Extent1].[EstimateHours] AS [EstimateHours], [Extent1].[DateLogged] AS [DateLogged], [Extent1].[DateModified] AS [DateModified], [Extent1].[CatagoryId] AS [CatagoryId2], [Extent2].[ProjectId] AS [ProjectId3], [Extent2].[ProjectName] AS [ProjectName2], [Extent2].[CreatedOn] AS [CreatedOn3], [Extent2].[CreatedBy] AS [CreatedBy3], [Extent2].[Active] AS [Active3], [Extent3].[CatagoryId] AS [CatagoryId1], [Extent3].[CatagoryName] AS [CatagoryName], [Extent3].[CreatedBy] AS [CreatedBy1], [Extent3].[CreatedOn] AS [CreatedOn1], [Extent3].[Active] AS [Active1], [Join3].[ApplicationId2], [Join3].[UserId4], [Join3].[UserName2], [Join3].[LoweredUserName2], [Join3].[MobileAlias2], [Join3].[IsAnonymous2], [Join3].[LastActivityDate2], [Join3].[UserId5], [Join3].[CompanyId1], [Join3].[Forename1], [Join3].[Surname1], [Join3].[Active4], [Extent6].[UserId] AS [UserId6], [Extent6].[CompanyId] AS [CompanyId2], [Extent6].[Forename] AS [Forename2], [Extent6].[Surname] AS [Surname2], [Extent6].[Active] AS [Active5], [Extent7].[ProjectId] AS [ProjectId1], [Extent7].[ProjectName] AS [ProjectName1], [Extent7].[CreatedOn] AS [CreatedOn2], [Extent7].[CreatedBy] AS [CreatedBy4], [Extent7].[Active] AS [Active2], [Extent8].[ProjectId] AS [ProjectId4], [Extent8].[ProjectName] AS [ProjectName3], [Extent8].[CreatedOn] AS [CreatedOn4], [Extent8].[CreatedBy] AS [CreatedBy2], [Extent8].[Active] AS [Active6], [Extent9].[TaskStatusId] AS [TaskStatusId1], [Extent9].[StatusName] AS [StatusName], [Extent10].[ApplicationId] AS [ApplicationId1], [Extent10].[UserId] AS [UserId1], [Extent10].[UserName] AS [UserName1], [Extent10].[LoweredUserName] AS [LoweredUserName1], [Extent10].[MobileAlias] AS [MobileAlias1], [Extent10].[IsAnonymous] AS [IsAnonymous1], [Extent10].[LastActivityDate] AS [LastActivityDate1], [Join10].[ApplicationId3], [Join10].[UserId7], [Join10].[UserName3], [Join10].[LoweredUserName3], [Join10].[MobileAlias3], [Join10].[IsAnonymous3], [Join10].[LastActivityDate3], [Join10].[ApplicationId4], [Join10].[UserId2], [Join10].[Password], [Join10].[PasswordFormat], [Join10].[PasswordSalt], [Join10].[MobilePIN], [Join10].[Email], [Join10].[LoweredEmail], [Join10].[PasswordQuestion], [Join10].[PasswordAnswer], [Join10].[IsApproved], [Join10].[IsLockedOut], [Join10].[CreateDate], [Join10].[LastLoginDate], [Join10].[LastPasswordChangedDate], [Join10].[LastLockoutDate], [Join10].[FailedPasswordAttemptCount], [Join10].[FailedPasswordAttemptWindowStart], [Join10].[FailedPasswordAnswerAttemptCount], [Join10].[FailedPasswordAnswerAttemptWindowStart], [Join10].[Comment]
FROM [dbo].[Tasks] AS [Extent1]
INNER JOIN [dbo].[Projects] AS [Extent2] ON [Extent1].[ProjectId] = [Extent2].[ProjectId]
LEFT OUTER JOIN [dbo].[Catagories] AS [Extent3] ON [Extent1].[CatagoryId] = [Extent3].[CatagoryId]
LEFT OUTER JOIN (SELECT [Extent4].[ApplicationId] AS [ApplicationId2], [Extent4].[UserId] AS [UserId4], [Extent4].[UserName] AS [UserName2], [Extent4].[LoweredUserName] AS [LoweredUserName2], [Extent4].[MobileAlias] AS [MobileAlias2], [Extent4].[IsAnonymous] AS [IsAnonymous2], [Extent4].[LastActivityDate] AS [LastActivityDate2], [Extent5].[UserId] AS [UserId5], [Extent5].[CompanyId] AS [CompanyId1], [Extent5].[Forename] AS [Forename1], [Extent5].[Surname] AS [Surname1], [Extent5].[Active] AS [Active4]
FROM [dbo].[aspnet_Users] AS [Extent4]
LEFT OUTER JOIN [dbo].[UserProfile] AS [Extent5] ON [Extent4].[UserId] = [Extent5].[UserId] ) AS [Join3] ON [Extent1].[AssignedTo] = [Join3].[UserId4]
INNER JOIN [dbo].[UserProfile] AS [Extent6] ON [Join3].[UserId5] = [Extent6].[UserId]
LEFT OUTER JOIN [dbo].[Projects] AS [Extent7] ON [Extent1].[ProjectId] = [Extent7].[ProjectId]
LEFT OUTER JOIN [dbo].[Projects] AS [Extent8] ON [Extent1].[ProjectId] = [Extent8].[ProjectId]
LEFT OUTER JOIN [dbo].[TaskStatuses] AS [Extent9] ON [Extent1].[TaskStatusId] = [Extent9].[TaskStatusId]
LEFT OUTER JOIN [dbo].[aspnet_Users] AS [Extent10] ON [Extent1].[LoggedBy] = [Extent10].[UserId]
LEFT OUTER JOIN (SELECT [Extent11].[ApplicationId] AS [ApplicationId3], [Extent11].[UserId] AS [UserId7], [Extent11].[UserName] AS [UserName3], [Extent11].[LoweredUserName] AS [LoweredUserName3], [Extent11].[MobileAlias] AS [MobileAlias3], [Extent11].[IsAnonymous] AS [IsAnonymous3], [Extent11].[LastActivityDate] AS [LastActivityDate3], [Extent12].[ApplicationId] AS [ApplicationId4], [Extent12].[UserId] AS [UserId2], [Extent12].[Password] AS [Password], [Extent12].[PasswordFormat] AS [PasswordFormat], [Extent12].[PasswordSalt] AS [PasswordSalt], [Extent12].[MobilePIN] AS [MobilePIN], [Extent12].[Email] AS [Email], [Extent12].[LoweredEmail] AS [LoweredEmail], [Extent12].[PasswordQuestion] AS [PasswordQuestion], [Extent12].[PasswordAnswer] AS [PasswordAnswer], [Extent12].[IsApproved] AS [IsApproved], [Extent12].[IsLockedOut] AS [IsLockedOut], [Extent12].[CreateDate] AS [CreateDate], [Extent12].[LastLoginDate] AS [LastLoginDate], [Extent12].[LastPasswordChangedDate] AS [LastPasswordChangedDate], [Extent12].[LastLockoutDate] AS [LastLockoutDate], [Extent12].[FailedPasswordAttemptCount] AS [FailedPasswordAttemptCount], [Extent12].[FailedPasswordAttemptWindowStart] AS [FailedPasswordAttemptWindowStart], [Extent12].[FailedPasswordAnswerAttemptCount] AS [FailedPasswordAnswerAttemptCount], [Extent12].[FailedPasswordAnswerAttemptWindowStart] AS [FailedPasswordAnswerAttemptWindowStart], [Extent12].[Comment] AS [Comment]
FROM [dbo].[aspnet_Users] AS [Extent11]
LEFT OUTER JOIN [dbo].[aspnet_Membership] AS [Extent12] ON [Extent11].[UserId] = [Extent12].[UserId] ) AS [Join10] ON [Extent1].[LoggedBy] = [Join10].[UserId7]
WHERE (1 = [Extent2].[Active]) AND ((1 = [Extent3].[Active]) OR ([Extent3].[CatagoryId] IS NULL)) ) AS [Filter1]
LEFT OUTER JOIN (SELECT [Extent13].[ApplicationId] AS [ApplicationId], [Extent13].[UserId] AS [UserId8], [Extent13].[UserName] AS [UserName], [Extent13].[LoweredUserName] AS [LoweredUserName], [Extent13].[MobileAlias] AS [MobileAlias], [Extent13].[IsAnonymous] AS [IsAnonymous], [Extent13].[LastActivityDate] AS [LastActivityDate], [Extent14].[UserId] AS [UserId3], [Extent14].[CompanyId] AS [CompanyId], [Extent14].[Forename] AS [Forename], [Extent14].[Surname] AS [Surname], [Extent14].[Active] AS [Active]
FROM [dbo].[aspnet_Users] AS [Extent13]
LEFT OUTER JOIN [dbo].[UserProfile] AS [Extent14] ON [Extent13].[UserId] = [Extent14].[UserId] ) AS [Join12] ON [Filter1].[LoggedBy] = [Join12].[UserId8]
WHERE (([Filter1].[TaskStatusId2] = #p__linq__49) OR (-1 = #p__linq__50)) AND (([Filter1].[ProjectId2] = #p__linq__51) OR (-1 = #p__linq__52)) AND (((CAST(CHARINDEX(#p__linq__53, [Filter1].[Subject]) AS int)) > 0) OR ((CAST(CHARINDEX(#p__linq__54, [Filter1].[Description]) AS int)) > 0) OR (N'''' = #p__linq__55) OR (#p__linq__56 IS NULL)) AND ([Filter1].[CompanyId2] = #p__linq__57) AND ((#p__linq__58 = #p__linq__59) OR ([Filter1].[LoggedBy] = #p__linq__60))
) AS [Project1]
ORDER BY [Project1].[TaskId] ASC',N'#p__linq__49 int,#p__linq__50 int,#p__linq__51 int,#p__linq__52 int,#p__linq__53 nvarchar(4000),#p__linq__54 nvarchar(4000),#p__linq__55 nvarchar(4000),#p__linq__56 nvarchar(4000),#p__linq__57 int,#p__linq__58 uniqueidentifier,#p__linq__59 uniqueidentifier,#p__linq__60 uniqueidentifier',#p__linq__49=1,#p__linq__50=1,#p__linq__51=2,#p__linq__52=2,#p__linq__53=NULL,#p__linq__54=NULL,#p__linq__55=NULL,#p__linq__56=NULL,#p__linq__57=1,#p__linq__58='00000000-0000-0000-0000-000000000000',#p__linq__59='00000000-0000-0000-0000-000000000000',#p__linq__60='00000000-0000-0000-0000-000000000000'
I'm sure there must be a way to get Linq to generate more friendly SQL. If I wrote this same query it could be done in about 5 joins and no inner selects, is it possible to get Linq to tidy this up?
Thanks
Gavin

The large query LINQ to EF creates is just a shortcoming of the first release of the Entity Framework. However, your query contains the phrase .OrderBy(SortField + " " + SortOrder), I believe the preffered way to write this would be .OrderBy(SortField).ThenBy(SortOrder). Also, is there any reason that you are using | instead of || and & instead of && in some places?
IQueryable<Tasks> tl = db.Tasks
.Include("Catagories")
.Include("Projects")
.Include("TaskStatuses")
.Include("AssignedTo")
.Where
(t => (t.TaskStatuses.TaskStatusId.Equals(currentStatus) | currentStatus == -1) &
(t.Projects.ProjectId.Equals(projectId) | projectId == -1) &
(t.Subject.Contains(SearchText) | t.Description.Contains(SearchText) | SearchText == "" | SearchText == null) &
(t.Projects.Active == true) &
(t.Catagories.Active == true || t.Catagories==null) &
(t.LoggedBy.UserProfile.Companies.CompanyId == CompanyId) &
(assignedToGuid == rnd | t.AssignedTo.UserId.Equals(assignedToGuid))).OrderBy(SortField + " " + SortOrder);

Related

C#: LINQ not returning the same result as SQL

I'm trying to convert the following SQL query to LINQ, but getting different result count with both,
SQL Query:
SELECT T5.CNTR, T5.BenefitCode,T5.ApprovedFlag,
T5.PaymentFrequencyCode, T5.InstalmentAmt, T5.TotalAmt,
T5.CarRego
FROM
dbo.EmployeeBenefit As T5
LEFT JOIN dbo.Payee ON T5.PayeeCntr = dbo.Payee.CNTR
LEFT JOIN dbo.BankDetails ON dbo.Payee.BankCntr = dbo.BankDetails.BankCntr
Left Join dbo.EmployeeCar As T4 on T5.EmployeeCarCntr=T4.Cntr
Inner Join dbo.EmployeeEntity As T1 On T5.EmployeeEntityCntr=T1.EmployeeEntityCntr
Inner Join dbo.EmployerEntity As T2 On T1.EmployerEntityCntr=T2.EmployerEntityCntr
where T5.EmployeeCntr = 117165
AND ((T5.EndDate is Null) OR (T5.EndDate >= GETDATE()))
LINQ:
var result = (from employeeBenefit in context.EmployeeBenefit
from payee in context.Payee.Where(x => x.Cntr == employeeBenefit.PayeeCntr).DefaultIfEmpty()
from bankDetails in context.BankDetails.Where(x => x.BankCntr == employeeBenefit.PayeeCntr).DefaultIfEmpty()
from employeeCar in context.EmployeeCar.Where(x => x.Cntr == payee.BankCntr).DefaultIfEmpty()
from employeeEntity in context.EmployeeEntity
where employeeEntity.EmployeeEntityCntr == employeeBenefit.EmployeeEntityCntr
from employeeEntity1 in context.EmployeeEntity
where employeeEntity.EmployerEntityCntr == employeeEntity1.EmployerEntityCntr
&& employeeBenefit.EmployeeCntr == iEmployeeID
&& (!employeeBenefit.EndDate.HasValue || employeeBenefit.EndDate >= DateTime.Now)
&& employeeBenefit.EmployeeCntr == 117165
&& employeeBenefit.CarRego == registration
select new
{
CNTR = employeeBenefit.Cntr,
BenefitCode = employeeBenefit.BenefitCode,
PaymentFrequencyCode = employeeBenefit.PaymentFrequencyCode,
InstalmentAmount = employeeBenefit.InstalmentAmt,
TotalAmount = employeeBenefit.TotalAmt,
CarRego = employeeBenefit.CarRego,
ApprovedFlag = employeeBenefit.ApprovedFlag
}).ToList();
Please let me know what i'm missing.
For the data in my database the SQL query is returning 10 records. But, the LINQ is returning 2700 records.
Not a full answer (I'm late for work) but:
var result = (from T5 in context.EmployeeBenefit
join PY in dbo.Payee on T5.PayeeCntr equals PY.CNTR into PY1
where T5.EmployeeCntr = 117165
select new {
CNTR = T5.Cntr,
...
}
).ToList();
It was the issue with the condition mismatch that i had done in the LINQ. The below query just worked fine. Thank you for helping me with the issue.
var result = (from employeeBenefit in context.EmployeeBenefit
from payee in context.Payee.Where(x => x.Cntr == employeeBenefit.PayeeCntr).DefaultIfEmpty()
from bankDetails in context.BankDetails.Where(x => x.BankCntr == payee.BankCntr).DefaultIfEmpty()
from employeeCar in context.EmployeeCar.Where(x => x.Cntr == employeeBenefit.EmployeeCarCntr).DefaultIfEmpty()
join employeeEntity in context.EmployeeEntity
on employeeBenefit.EmployeeEntityCntr equals employeeEntity.EmployeeEntityCntr
join employerEntity in context.EmployerEntity
on employeeEntity.EmployerEntityCntr equals employerEntity.EmployerEntityCntr
where employeeBenefit.EmployeeCntr == 117165 && (!employeeBenefit.EndDate.HasValue || employeeBenefit.EndDate >= DateTime.Now)
select new
{
CNTR = employeeBenefit.Cntr,
BenefitCode = employeeBenefit.BenefitCode,
PaymentFrequencyCode = employeeBenefit.PaymentFrequencyCode,
InstalmentAmount = employeeBenefit.InstalmentAmt,
TotalAmount = employeeBenefit.TotalAmt,
CarRego = employeeBenefit.CarRego,
ApprovedFlag = employeeBenefit.ApprovedFlag
}).ToList();

converting sql to linq (joins and group by)

I am converting an old webforms app to asp.net mvc and I am having issues converting one of my sql statements into linq. In particular, i need help with grouping and joins. I have tried several ways by looking at various examples here and none have worked for me.
SELECT cp.PartNumber, cp.PartDescription, PFEP.PFEPTx, PFEP.KBQty,
TX_QOH.QOH, TX_ReworkQOH.Rework_QOH as Rework, SUM(ShippingInput.Qty) AS
'Ocean'
FROM CustomerParts as cp
LEFT JOIN TX_QOH
ON cp.PartNumber = TX_QOH.PN
LEFT JOIN TX_ReworkQOH
ON cp.PartNumber = TX_ReworkQOH.PN
LEFT JOIN ShippingInput
ON cp.PartNumber = ShippingInput.PN AND ShippingInput.Status <> 'Received'
LEFT JOIN PFEP
ON cp.PartNumber= PFEP.PN
WHERE cp.PartType = 'Actuator Part' AND cp.Division = 'Bayne' AND cp.Active
= 'Yes' AND TX_QOH.QOH = '0'
Group By cp.PartNumber, TX_QOH.QOH, TX_ReworkQOH.Rework_QOH,
cp.PartDescription, PFEP.PFEPTx, PFEP.KBQty
Order By cp.PartNumber ASC
This is obviously untested, and there may be null issues with trying to access fields when they may not exist due to the left join (e.g. SUM(ShippingInput.Qty)), which is why I moved some of the tests to lambda Where on the join
from cp in CustomerParts
join r_tx_qoh in TX_QOH.Where(r => r.QOH == "0") on cp.PartNumber equals r_tx_qoh.PN into j_tx_qoh
from r_tx_qoh in j_tx_qoh.DefaultIfEmpty()
join r_tx_reworkqoh in TX_ReworkQOH on cp.PartNumber equals r_tx_reworkqoh.PN into j_tx_reworkqoh
from r_tx_reworkqoh in j_tx_reworkqoh.DefaultIfEmpty()
join r_shippinginput in ShippingInput.Where(r => r.Status != "Received") on cp.PartNumber equals r_shippinginput.PN into j_shippinginput
from r_shippinginput in j_shippinginput.DefaultIfEmpty()
join r_pfep in PFEP on cp.PartNumber equals r_pfep.PN into j_pfep
from r_pfep in j_pfep.DefaultIfEmpty()
where cp.PartType == "Actuator Part" && cp.Division == "Bayne" && cp.Active == "Yes"
group new { cp, r_pfep, r_tx_qoh, r_tx_reworkqoh, r_shippinginput } by new { cp.PartNumber, r_tx_qoh.QOH, r_tx_reworkqoh.Rework_QOH, cp.PartDescription, r_pfep.PFEPTx, r_pfep.KBQty } into gcp
orderby gcp.Key.PartNumber
select new { gcp.Key.PartNumber, gcp.Key.PartDescription, gcp.Key.PFEPTx, gcp.Key.KBQty, tcp.Key.QOH, Rework = gcp.Key.Rework_QOH, Ocean = gcp.Sum(r => r.r_shippinginput.Qty) }
LINQ Version
var queryNew = (from cp in db.MasterPartLists
join tx in db.TxQohs on cp.CustomerPn equals tx.Pn into jTxQoh
from tx in jTxQoh.DefaultIfEmpty()
join c in db.ShipIns.Where(r => r.ShipInStatusId != 3) on cp.CustomerPn equals c.Pn into jShipIns
from c in jShipIns.DefaultIfEmpty()
join d in db.Pfeps on cp.CustomerPn equals d.CustomerPn into jPfeps
from d in jPfeps.DefaultIfEmpty()
where d.PartTypeId == parttype && cp.CustomerDivisionId == division && cp.ActivePartId == 1 && tx.Qoh == 0
group new {cp, d, tx, c} by new {cp.CustomerPn, tx.Qoh, cp.PartDescription, d.PfepTx, d.KbQty}
into gcp
orderby gcp.Key.CustomerPn
select new
{
gcp.Key.CustomerPn,
gcp.Key.PartDescription,
gcp.Key.PfepTx,
gcp.Key.KbQty,
gcp.Key.Qoh,
Ocean = (int?)gcp.Sum(r => r.c.Qty)
});
SQL Version
var queryNew = "SELECT cp.CustomerPn, cp.PartDescription, Pfeps.PFEPTx, Pfeps.KBQty, TxQohs.Qoh, SUM(ShipIns.Qty) AS 'Ocean' "
+ "FROM MasterPartLists as cp "
+ "LEFT JOIN TxQohs "
+ "ON cp.CustomerPn = TxQohs.Pn AND TxQohs.Qoh = '0' "
+ "LEFT JOIN ShipIns "
+ "ON cp.CustomerPn = ShipIns.Pn AND ShipIns.ShipStatusId <> '3' "
+ "LEFT JOIN Pfep "
+ "ON cp.CustomerPn = Pfeps.CustomerPn "
+ "WHERE cp.PartTypeId = parttype AND cp.CustomerDivisionId = division AND cp.ActivePartId = '1' "
+ "Group By cp.CustomerPn, TxQohs.Qoh, cp.PartDescription, Pfeps.PfepTx, Pfeps.KbQty "
+ "Order By cp.CustomerPn ASC ";

left join do not show all records

In following code left join do not show all the records from left !!!
select *,CASE WHEN (ResDEBIT> ResCREDIT) THEN (ResDEBIT) when (ResCREDIT> ResDEBIT)then (ResCREDIT) else 0 END AS Mande,CASE WHEN (ResDEBIT> ResCREDIT) THEN ('debit') when (ResCREDIT> ResDEBIT)then ('credit') ELSE ('ziro') END AS Status from(SELECT Sales.CustomerInfo.CustomerInfoID,FullTitle=(cast(Sales.CustomerInfo.AccountFK as nvarchar)+' - '+Sales.CustomerInfo.FullName), Sales.CustomerInfo.TopicFK, Sales.CustomerInfo.AccountFK,Sales.CustomerInfo.CompanyRegNo,Sales.CustomerInfo.PersonTypeFK,Sales.CustomerInfo.BankAccountDetail,Sales.CustomerInfo.BankAccountNo, Sales.CustomerInfo.AccountNo, Sales.CustomerInfo.FullName,
Sales.CustomerInfo.Birthdate, Sales.CustomerInfo.TitleFK, Sales.CustomerInfo.RegistrationDate, Sales.CustomerInfo.CustomerPhotoFK, Sales.CustomerInfo.SocialNo,
Sales.CustomerInfo.WebPage, Sales.CustomerInfo.JobFK, Sales.CustomerInfo.MaxDebitLimit, Sales.CustomerInfo.MaxChequeCredit,
Sales.CustomerInfo.PreferedPaymentMethodFK, Sales.CustomerInfo.FirstBalanceKind, Sales.CustomerInfo.FirstBalance, Sales.CustomerInfo.Debit,
Sales.CustomerInfo.Credit, Sales.CustomerInfo.Note, Sales.CustomerInfo.FinancialPeriodFK, Sales.CustomerInfo.CompanyInfoFK,
isnull(SUM(Accounting.DocumentDetail.Debit),0) AS Debit1, isnull(SUM(Accounting.DocumentDetail.Credit),0) AS Credit1, (CASE WHEN (isnull(SUM(Accounting.DocumentDetail.Credit),0)
- isnull(SUM(Accounting.DocumentDetail.Debit),0)) < 0 THEN (isnull(SUM(Accounting.DocumentDetail.Debit),0) - isnull(SUM(Accounting.DocumentDetail.Credit),0)) ELSE 0 END) AS ResDEBIT,
(CASE WHEN (isnull(SUM(Accounting.DocumentDetail.Credit),0) - isnull(SUM(Accounting.DocumentDetail.Debit),0)) > 0 THEN (isnull(SUM(Accounting.DocumentDetail.Credit),0)
- isnull(SUM(Accounting.DocumentDetail.Debit),0)) ELSE 0 END) AS ResCREDIT,Sales.CustomerInfo.BlackListed, Sales.CustomerInfo.IsActive
FROM Sales.CustomerInfo left JOIN
Accounting.DocumentDetail ON Sales.CustomerInfo.AccountFK = Accounting.DocumentDetail.TopicFK
GROUP BY Sales.CustomerInfo.CustomerInfoID, Sales.CustomerInfo.TopicFK, Sales.CustomerInfo.AccountFK, Sales.CustomerInfo.AccountNo,
Sales.CustomerInfo.FullName, Sales.CustomerInfo.Birthdate, Sales.CustomerInfo.TitleFK,Sales.CustomerInfo.CompanyRegNo,Sales.CustomerInfo.PersonTypeFK,Sales.CustomerInfo.BankAccountDetail,Sales.CustomerInfo.BankAccountNo, Sales.CustomerInfo.RegistrationDate,
Sales.CustomerInfo.CustomerPhotoFK, Sales.CustomerInfo.SocialNo, Sales.CustomerInfo.WebPage, Sales.CustomerInfo.JobFK, Sales.CustomerInfo.MaxDebitLimit,
Sales.CustomerInfo.MaxChequeCredit, Sales.CustomerInfo.PreferedPaymentMethodFK, Sales.CustomerInfo.FirstBalanceKind, Sales.CustomerInfo.FirstBalance,
Sales.CustomerInfo.Debit, Sales.CustomerInfo.Credit, Sales.CustomerInfo.Note, Sales.CustomerInfo.FinancialPeriodFK, Sales.CustomerInfo.CompanyInfoFK,
Sales.CustomerInfo.BlackListed, Sales.CustomerInfo.IsActive) CustomerInfo
check how many distinct record exists for your group by columns
Select distinct
Sales.CustomerInfo.CustomerInfoID
,Sales.CustomerInfo.TopicFK
,Sales.CustomerInfo.AccountFK
,Sales.CustomerInfo.AccountNo
,Sales.CustomerInfo.FullName
,Sales.CustomerInfo.Birthdate
,Sales.CustomerInfo.TitleFK
,Sales.CustomerInfo.CompanyRegNo
,Sales.CustomerInfo.PersonTypeFK
,Sales.CustomerInfo.BankAccountDetail
,Sales.CustomerInfo.BankAccountNo
,Sales.CustomerInfo.RegistrationDate
,Sales.CustomerInfo.CustomerPhotoFK
,Sales.CustomerInfo.SocialNo
,Sales.CustomerInfo.WebPage
,Sales.CustomerInfo.JobFK
,Sales.CustomerInfo.MaxDebitLimit
,Sales.CustomerInfo.MaxChequeCredit
,Sales.CustomerInfo.PreferedPaymentMethodFK
,Sales.CustomerInfo.FirstBalanceKind
,Sales.CustomerInfo.FirstBalance
,Sales.CustomerInfo.Debit
,Sales.CustomerInfo.Credit
,Sales.CustomerInfo.Note
,Sales.CustomerInfo.FinancialPeriodFK
,Sales.CustomerInfo.CompanyInfoFK
,Sales.CustomerInfo.BlackListed
,Sales.CustomerInfo.IsActive
from Sales.CustomerInfo
the number of return records for your above query will be same...To get all records from your left table you can use any one of the below 2 methods but i would prefer the 2nd one
1)use sub query
2)first do your aggregation in a separate query and join it with your left table again... the query should be some thing similar to below code:
;WITH CTE ( AccountFK, Debit1 ,Credit1 ,ResDEBIT ,ResCREDIT )
AS (
SELECT
Sales.CustomerInfo.AccountFK
,isnull(SUM(Accounting.DocumentDetail.Debit), 0) AS Debit1
,isnull(SUM(Accounting.DocumentDetail.Credit), 0) AS Credit1
,(
CASE
WHEN (isnull(SUM(Accounting.DocumentDetail.Credit), 0) - isnull(SUM(Accounting.DocumentDetail.Debit), 0)) < 0
THEN (isnull(SUM(Accounting.DocumentDetail.Debit), 0) - isnull(SUM(Accounting.DocumentDetail.Credit), 0))
ELSE 0
END
) AS ResDEBIT
,(
CASE
WHEN (isnull(SUM(Accounting.DocumentDetail.Credit), 0) - isnull(SUM(Accounting.DocumentDetail.Debit), 0)) > 0
THEN (isnull(SUM(Accounting.DocumentDetail.Credit), 0) - isnull(SUM(Accounting.DocumentDetail.Debit), 0))
ELSE 0
END
) AS ResCREDIT
FROM Sales.CustomerInfo
LEFT JOIN Accounting.DocumentDetail ON Sales.CustomerInfo.AccountFK = Accounting.DocumentDetail.TopicFK
GROUP BY Sales.CustomerInfo.CustomerInfoID
,Sales.CustomerInfo.TopicFK
,Sales.CustomerInfo.AccountFK
,Sales.CustomerInfo.AccountNo
,Sales.CustomerInfo.FullName
,Sales.CustomerInfo.Birthdate
,Sales.CustomerInfo.TitleFK
,Sales.CustomerInfo.CompanyRegNo
,Sales.CustomerInfo.PersonTypeFK
,Sales.CustomerInfo.BankAccountDetail
,Sales.CustomerInfo.BankAccountNo
,Sales.CustomerInfo.RegistrationDate
,Sales.CustomerInfo.CustomerPhotoFK
,Sales.CustomerInfo.SocialNo
,Sales.CustomerInfo.WebPage
,Sales.CustomerInfo.JobFK
,Sales.CustomerInfo.MaxDebitLimit
,Sales.CustomerInfo.MaxChequeCredit
,Sales.CustomerInfo.PreferedPaymentMethodFK
,Sales.CustomerInfo.FirstBalanceKind
,Sales.CustomerInfo.FirstBalance
,Sales.CustomerInfo.Debit
,Sales.CustomerInfo.Credit
,Sales.CustomerInfo.Note
,Sales.CustomerInfo.FinancialPeriodFK
,Sales.CustomerInfo.CompanyInfoFK
,Sales.CustomerInfo.BlackListed
,Sales.CustomerInfo.IsActive
)
SELECT Sales.CustomerInfo.CustomerInfoID
,FullTitle = (cast(Sales.CustomerInfo.AccountFK AS NVARCHAR) + ' - ' + Sales.CustomerInfo.FullName)
,Sales.CustomerInfo.TopicFK
,Sales.CustomerInfo.AccountFK
,Sales.CustomerInfo.CompanyRegNo
,Sales.CustomerInfo.PersonTypeFK
,Sales.CustomerInfo.BankAccountDetail
,Sales.CustomerInfo.BankAccountNo
,Sales.CustomerInfo.AccountNo
,Sales.CustomerInfo.FullName
,Sales.CustomerInfo.Birthdate
,Sales.CustomerInfo.TitleFK
,Sales.CustomerInfo.RegistrationDate
,Sales.CustomerInfo.CustomerPhotoFK
,Sales.CustomerInfo.SocialNo
,Sales.CustomerInfo.WebPage
,Sales.CustomerInfo.JobFK
,Sales.CustomerInfo.MaxDebitLimit
,Sales.CustomerInfo.MaxChequeCredit
,Sales.CustomerInfo.PreferedPaymentMethodFK
,Sales.CustomerInfo.FirstBalanceKind
,Sales.CustomerInfo.FirstBalance
,Sales.CustomerInfo.Debit
,Sales.CustomerInfo.Credit
,Sales.CustomerInfo.Note
,Sales.CustomerInfo.FinancialPeriodFK
,Sales.CustomerInfo.CompanyInfoFK
,cte.Debit1
,cte.Credit1
,cte.ResDEBIT
,cte.ResCREDIT
,Sales.CustomerInfo.BlackListed
,Sales.CustomerInfo.IsActive
,CASE
WHEN (ResDEBIT > ResCREDIT)
THEN (ResDEBIT)
WHEN (ResCREDIT > ResDEBIT)
THEN (ResCREDIT)
ELSE 0
END AS Mande
,CASE
WHEN (ResDEBIT > ResCREDIT)
THEN ('debit')
WHEN (ResCREDIT > ResDEBIT)
THEN ('credit')
ELSE ('ziro')
END AS STATUS
FROM Sales.CustomerInfo
LEFT JOIN cte ON Sales.CustomerInfo.AccountFK = cte.AccountFK

Query performance to compare date with many join and entity framework

I have this database model :
I use this query :
public List<Film> ListFilmsSortiesDes7DerniersJoursDVD()
{
DateTime dateDans7Jours = DateTime.Now.AddDays(7);
DateTime dateIlYa7Jours = DateTime.Now.AddDays(-7);
return Query(f => f.Releases.Where(r => r.Langue.langue_code == "FR" && r.TypeRelease.typerelease_code == "DVD").FirstOrDefault().release_date > dateIlYa7Jours
&& f.Releases.Where(r => r.Langue.langue_code == "FR" && r.TypeRelease.typerelease_code == "DVD").FirstOrDefault().release_date < dateDans7Jours && !string.IsNullOrEmpty(f.film_image)).ToList();
}
But the SQL generated have bad performance, about 1.3 seconds to return results (with SQL Server Express 2008 and I already have Index on correct fields):
SELECT [Extent1].[film_id] AS [film_id],
[Extent1].[film_image] AS [film_image],
[Extent1].[film_image_thumb] AS [film_image_thumb],
[Extent1].[film_format] AS [film_format],
[Extent1].[film_motsclefs] AS [film_motsclefs],
[Extent1].[film_nom] AS [film_nom],
[Extent1].[film_nomvf] AS [film_nomvf],
[Extent1].[film_synopsis] AS [film_synopsis],
[Extent1].[film_anneeproduction] AS [film_anneeproduction],
[Extent1].[film_budget] AS [film_budget],
[Extent1].[film_dateajout] AS [film_dateajout],
[Extent1].[film_actif] AS [film_actif],
[Extent1].[utilisateur_id] AS [utilisateur_id],
[Extent1].[film_francais] AS [film_francais],
[Extent1].[film_revenue] AS [film_revenue],
[Extent1].[filmgroupe_id] AS [filmgroupe_id]
FROM [dbo].[Film] AS [Extent1]
OUTER APPLY (SELECT TOP (1) [Filter1].[release_date] AS [release_date]
FROM (SELECT [Extent2].[film_id] AS [film_id],
[Extent3].[release_date] AS [release_date],
[Extent3].[typerelease_id] AS [typerelease_id]
FROM [dbo].[FilmRelease] AS [Extent2]
INNER JOIN [dbo].[Release] AS [Extent3]
ON [Extent3].[release_id] = [Extent2].[release_id]
INNER JOIN [dbo].[Langue] AS [Extent4]
ON [Extent3].[langue_id] = [Extent4].[langue_id]
WHERE N'FR' = [Extent4].[langue_code]) AS [Filter1]
INNER JOIN [dbo].[TypeRelease] AS [Extent5]
ON [Filter1].[typerelease_id] = [Extent5].[typerelease_id]
WHERE ([Extent1].[film_id] = [Filter1].[film_id])
AND (N'CINEMA' = [Extent5].[typerelease_code])) AS [Limit1]
CROSS APPLY (SELECT TOP (1) [Filter3].[release_date] AS [release_date]
FROM (SELECT [Extent6].[film_id] AS [film_id],
[Extent7].[release_date] AS [release_date],
[Extent7].[typerelease_id] AS [typerelease_id]
FROM [dbo].[FilmRelease] AS [Extent6]
INNER JOIN [dbo].[Release] AS [Extent7]
ON [Extent7].[release_id] = [Extent6].[release_id]
INNER JOIN [dbo].[Langue] AS [Extent8]
ON [Extent7].[langue_id] = [Extent8].[langue_id]
WHERE N'FR' = [Extent8].[langue_code]) AS [Filter3]
INNER JOIN [dbo].[TypeRelease] AS [Extent9]
ON [Filter3].[typerelease_id] = [Extent9].[typerelease_id]
WHERE ([Extent1].[film_id] = [Filter3].[film_id])
AND (N'CINEMA' = [Extent9].[typerelease_code])) AS [Limit2]
WHERE ([Limit1].[release_date] > '2013-02-04T00:07:48' /* #p__linq__0 */)
AND ([Limit2].[release_date] < '2013-02-18T00:07:48' /* #p__linq__1 */)
AND ([Extent1].[film_image] IS NOT NULL)
Do you please have any ideas to improve performance of this query ?
Ok why search complicated when the answer is simple :
public List<Film> ListFilmsSortiesDes7DerniersJoursCinema()
{
DateTime dateDans7Jours = DateTime.Now.AddDays(7);
DateTime dateIlYa7Jours = DateTime.Now.AddDays(-7);
return Query(f => f.Releases.Where(r => r.Langue.langue_code == "FR" && r.TypeRelease.typerelease_code == "CINEMA" && r.release_date > dateIlYa7Jours && r.release_date < dateDans7Jours).Any()).ToList();
}
I did a join in too

LINQ EF Join with added CROSS JOIN

This linq to ef syntax produces the sql syntax shown below. How can I get it to produce without the CROSS JOIN? The cross join is giving me a ton of extra records.
vehicleList = (from _vehicle in shireyContext.Vehicles
join _statusDescription in shireyContext.StatusDescriptions
on _vehicle.Status equals _statusDescription.StatusId
join _newOptions2 in shireyContext.VehicleOption_New
on _vehicle.StockNo equals _newOptions2.StockNo
where _vehicle.NewOrUsed == NewOrUsed && _vehicle.Model == Model && _newOptions2.Color != null
from _newOptions in shireyContext.VehicleOption_New
select new VehicleDomainEntity
{
StockNo = _vehicle.StockNo,
Year = _vehicle.VehicleYear,
Make = _vehicle.Make,
Model = _vehicle.Model,
Description = _newOptions2.Description,
ExteriorColor = _vehicle.ExteriorColor,
InteriorColor = _vehicle.InteriorColor,
InternetPrice = _vehicle.CodedCost,
ListPrice = _vehicle.ListPrice,
Status = _statusDescription.StatusDescriptionText,
NewOrUsed = _vehicle.NewOrUsed,
Mileage = _vehicle.Mileage,
VIN = _vehicle.VIN
}).ToList();
produces this sql:
SELECT
Extent2.StatusId AS StatusId,
Extent1.StockNo AS StockNo,
Extent1.VehicleYear AS VehicleYear,
Extent1.Make AS Make,
Extent1.Model AS Model,
Extent3.Description AS Description,
Extent1.ExteriorColor AS ExteriorColor,
Extent1.InteriorColor AS InteriorColor,
Extent1.CodedCost AS CodedCost,
Extent1.ListPrice AS ListPrice,
Extent2.StatusDescriptionText AS StatusDescriptionText,
Extent1.NewOrUsed AS NewOrUsed,
Extent1.Mileage AS Mileage,
Extent1.VIN AS VIN
FROM dbo.Vehicles AS Extent1
INNER JOIN dbo.StatusDescription AS Extent2 ON Extent1.Status = Extent2.StatusId
INNER JOIN dbo.VehicleOption_New AS Extent3 ON Extent1.StockNo = Extent3.StockNo
CROSS JOIN dbo.VehicleOption_New AS Extent4
WHERE (Extent1.NewOrUsed = 'N') AND (Extent1.Model = 'cts' AND (Extent3.Color IS NOT NULL))
I think you want this
from _vehicle in shireyContext.Vehicles
join _statusDescription in shireyContext.StatusDescriptions
on _vehicle.Status equals _statusDescription.StatusId
join _newOptions2 in shireyContext.VehicleOption_New into VehicleNew
on _vehicle.StockNo equals _newOptions2.StockNo
where _vehicle.NewOrUsed == NewOrUsed && _vehicle.Model == Model && _newOptions2.Color != null
from _newOptions in VehicleNew
The two lines that are changed are:
join _newOptions2 in shireyContext.VehicleOption_New into VehicleNew
and
from _newOptions in VehicleNew

Resources