I am using EF 6, ASP.NET for Windows
I have this SQL statement that looks like this:
SELECT M.STMTDT, M.stmtno, ISNULL(SUM(M.PayAmount),0) as Fee, ISNULL(SUM(A.Amount),0) as Adjustment, ISNULL(SUM(M.PayAmount) + SUM(A.Amount),0) as Total FROM MainData M
LEFT OUTER JOIN Adjustments A
ON M.STMTDT = A.STMTDT AND M.stmtno = A.Stmtno
where M.CID= '334R' AND YEAR(M.stmtdt) > year(getdate())-4
GROUP BY M.STMTDT, M.stmtno
This is a fairly standard query that groups, combines, and summarizes. I would like to create the same query in LINQ, but it's hard to do.
This is my LINQ query:
var fourYearsAgo = DateTime.Now.AddYears(-4).Year;
var dataWithoutGrouping = from m in MainData
where m.CID == "334r" && m.STMTDT.Value.Year > fourYearsAgo
join a in Adjustments
on new {m.STMTDT, m.Stmtno} equals new {a.STMTDT, a.Stmtno} into grp
from ja in grp.DefaultIfEmpty()
select new {
Dt = m.STMTDT,
No = m.Stmtno,
Fee = m.PayAmount,
Adjustment = ja.Amount
};
var data = (from b in dataWithoutGrouping
group b by new {b.Dt, b.No }into grp
select new {
StatmentFee = grp.Sum(x => x.Fee),
StatementAdjustments = grp.Sum(x => x.Adjustment),
StatementDate = grp.FirstOrDefault().Dt,
StatementNo = grp.FirstOrDefault().No
}).ToList();
What this SQL produces:
DECLARE @p0 VarChar(1000) = '334r'
DECLARE @p1 Int = 2014
SELECT [t3].[value] AS [StatmentFee], [t3].[value2] AS [StatementAdjustments], (
SELECT [t6].[STMTDT]
FROM (
SELECT TOP (1) [t4].[STMTDT]
FROM [MainData] AS [t4]
LEFT OUTER JOIN [Adjustments] AS [t5] ON ([t4].[STMTDT] = [t5].[STMTDT]) AND ([t4].[stmtno] = [t5].[Stmtno])
WHERE ((([t3].[STMTDT] IS NULL) AND ([t4].[STMTDT] IS NULL)) OR (([t3].[STMTDT] IS NOT NULL) AND ([t4].[STMTDT] IS NOT NULL) AND ((([t3].[STMTDT] IS NULL) AND ([t4].[STMTDT] IS NULL)) OR (([t3].[STMTDT] IS NOT NULL) AND ([t4].[STMTDT] IS NOT NULL) AND ([t3].[STMTDT] = [t4].[STMTDT]))))) AND ((([t3].[stmtno] IS NULL) AND ([t4].[stmtno] IS NULL)) OR (([t3].[stmtno] IS NOT NULL) AND ([t4].[stmtno] IS NOT NULL) AND ((([t3].[stmtno] IS NULL) AND ([t4].[stmtno] IS NULL)) OR (([t3].[stmtno] IS NOT NULL) AND ([t4].[stmtno] IS NOT NULL) AND ([t3].[stmtno] = [t4].[stmtno]))))) AND ([t4].[CID] = @p0) AND (DATEPART(Year, [t4].[STMTDT]) > @p1)
) AS [t6]
) AS [StatementDate], (
SELECT [t9].[stmtno]
FROM (
SELECT TOP (1) [t7].[stmtno]
FROM [MainData] AS [t7]
LEFT OUTER JOIN [Adjustments] AS [t8] ON ([t7].[STMTDT] = [t8].[STMTDT]) AND ([t7].[stmtno] = [t8].[Stmtno])
WHERE ((([t3].[STMTDT] IS NULL) AND ([t7].[STMTDT] IS NULL)) OR (([t3].[STMTDT] IS NOT NULL) AND ([t7].[STMTDT] IS NOT NULL) AND ((([t3].[STMTDT] IS NULL) AND ([t7].[STMTDT] IS NULL)) OR (([t3].[STMTDT] IS NOT NULL) AND ([t7].[STMTDT] IS NOT NULL) AND ([t3].[STMTDT] = [t7].[STMTDT]))))) AND ((([t3].[stmtno] IS NULL) AND ([t7].[stmtno] IS NULL)) OR (([t3].[stmtno] IS NOT NULL) AND ([t7].[stmtno] IS NOT NULL) AND ((([t3].[stmtno] IS NULL) AND ([t7].[stmtno] IS NULL)) OR (([t3].[stmtno] IS NOT NULL) AND ([t7].[stmtno] IS NOT NULL) AND ([t3].[stmtno] = [t7].[stmtno]))))) AND ([t7].[CID] = @p0) AND (DATEPART(Year, [t7].[STMTDT]) > @p1)
) AS [t9]
) AS [StatementNo]
FROM (
SELECT SUM([t2].[PayAmount]) AS [value], SUM([t2].[value]) AS [value2], [t2].[STMTDT], [t2].[stmtno]
FROM (
SELECT [t0].[STMTDT], [t0].[stmtno], [t0].[PayAmount], [t1].[Amount] AS [value], [t0].[CID]
FROM [MainData] AS [t0]
LEFT OUTER JOIN [Adjustments] AS [t1] ON ([t0].[STMTDT] = [t1].[STMTDT]) AND ([t0].[stmtno] = [t1].[Stmtno])
) AS [t2]
WHERE ([t2].[CID] = @p0) AND (DATEPART(Year, [t2].[STMTDT]) > @p1)
GROUP BY [t2].[STMTDT], [t2].[stmtno]
) AS [t3]
As you can see, this SQL is extremely inefficient compared to the original expression.
Please someone can help me convert LINQ to create the original SQL shown above.
Also, I cannot use SQL for unexplained reasons, sorry!
Edit
Sample data:
MainData:
StmtDate | | StmtNo | Pay
2016-01-29 | 00: 00: 00.000 | 3124360 | 25.00
2016-02-12 | 00: 00: 00.000 | 3124391 | 50.00
2016-01-29 | 00: 00: 00.000 | 3124360 | 600.00
2016-02-12 | 00: 00: 00.000 | 3124391 | 75.00
Adjustments:
StmtDate | STMTNO | Adj
2016-01-29 | 00: 00: 00.000 | 3124360 0,00
2016-02-12 | 00: 00: 00.000 | 3124391 0,00
2016-01-29 | 00: 00: 00.000 | 3124360 120,00
2016-02-12 | 00: 00: 00.000 | 3124391 60,00
:
StmtDate | StmtNo | | Adj | Total
2016-01-29 00: 00: 00.000 | 3124360 | 25.00 | 0.00 | 0.00
2016-02-12 00: 00: 00.000 | 3124391 | 50.00 | 0.00 | 0.00
2016-02-19 00: 00: 00.000 | 3124404 | 600.00 | 120.00 | 720.00
2016-02-19 00: 00: 00.000 | 3124405 | 75.00 | 60.00 | 135.00