I am trying to convert a SQL statement to Linq/Entity Framework. I'm pretty new to working with SQL and am having a difficult time. Below is the SQL.
DECLARE @tbl TABLE (
RowNum INT, FName VARCHAR(9), MInitial VARCHAR(1),
LName VARCHAR(30), LegalAddress VARCHAR(50), MailAddress VARCHAR(50),
AmDescr VARCHAR(50), EmpCount DECIMAL, EmpStatus SmallInt, Occupation VARCHAR(40) )
INSERT INTO @tbl
SELECT
ROW_NUMBER() OVER(ORDER BY LName ASC) AS RowNum,
FName,
MInitial,
LName,
LegalAddress,
MailAddress,
AmDescr,
agent.EmpCount,
agent.EmpStatus,
agentEmployer.Occupation
FROM (
SELECT
trust.FName,
trust.MInitial,
trust.LName
tla.Address,
tma.Address,
at.Descr,
trust.EmpStatus
(SELECT MAX(EMPCOUNT) FROM AGENTEMPLOYERS WHERE agent.SSN = trust.SSN) AS EmpCount
FROM CLIENTSSUITS cs
INNER JOIN TRUSTS trust ON trust.SSN = cs.CLIENT
FULL JOIN ADV_TYPES at ON at.CODE = trust.AT
LEFT OUTER JOIN CLIENTADDRESSES tla ON tla.SSN = trust.SSN AND tla.ID = 'L'
LEFT OUTER JOIN CLIENTADDRESSES tma ON tma.SSN = trust.SSN AND tma.ID = 'M'
WHERE cs.PRIMARY = w AND SecondaryRole = x AND cs.ID = y AND cs.Rev = z AND cs.DELETED = 0
GROUP BY trust.FName,
trust.MName,
trust.LName,
tla.Address,
tma.Address,
at.Descr,
trust.EmpStatus
) agent
LEFT OUTER JOIN AGENTEMPLOYERS agentEmployer on agentEmployer.SSN = agent.SSN AND agentEmployer.EmpCount = agent.EmpCount
What's giving me the most trouble is the GROUP BY
statement, the agent
variable (alias), and the final LEFT OUTER JOIN
on AGENTEMPLOYERS
.
When I try to write the inner SELECT ... FROM CLIENTSUITS
, the GROUP BY
is throwing me off. I end up with an IGrouping
object which I can't figure out how to use.
Is the 'agent' variable just holding the result of the SELECT ... FROM CLIENTSUITS
block? I've never seen SQL written like that before. Additionally, in the outer INSERT INTO @tbl
, the EmpCounter
and EmpStatus
values are coming off of 'agent', but the inner SELECT ... FROM CLIENTSUITS
portion it is coming off trust. (I guess if the 'agent' variable just holds the result of the inner SELECT ... FROM CLIENTSUITS
then I think it's the same?).
And the final LEFT OUTER JOIN
, seems weird to me. Is it just doing a join on the result of 'agent'? What would the advantage be to writing it this way as opposed to having it in the inner SQL statement?
Thank you in advance for any answers helping me get this converted to EF Linq.
EDIT: Attempt at solution. I get all the ungrouped data, then group it, then try to do the final LEFT OUTER JOIN
on the grouped data, but at HERE_1 I have access to an IGrouping
object, which I can't figure out what to do with. And then at HERE_2 I was planning to construct the object with all the values I need.
I see now that I'm missing RowNum now, but I think I should be able to order it by LName then convert to a list and still effectively have RowNum by iterating over the list.
var tblDataUngrouped = (from cs in ctx.Clientsuits
// inner join on trusts
join trust in ctx.Trusts
on cs.Client equals trust.Ssn
// join on AdvTypes
join at in ctx.AdvTypes
on trust.AT equals at.Code into temp
from subAT in temp.DefaultIfEmpty()
// join on Clientaddresses, Legal
join tla in ctx.Clientaddresses
on new { ssn = trust.Ssn, psind = "L" } equals new { ssn = tla.Ssn, psind = tla.Psind } into temp2
from subTla in temp2.DefaultIfEmpty()
// join on Clientaddresses, Mail
join tma in ctx.Clientaddresses
on new { ssn = trust.Ssn, psind = "M" } equals new { ssn = tma.Ssn, psind = tma.Psind } into temp3
from subTma in temp3.DefaultIfEmpty()
where cs.Primaryclient == w && cs.SecondaryRole == x && cs.Idnum == y && cs.Revnum == z && cs.Deleted == 0
select new
{
trustee.Firstname,
trustee.Middleinitial,
trustee.Lastname,
trust.EmpStatus,
legalAddr = subTla.Address,
mailAddr = subTma.Address,
atDescr = subAT.Descr,
empCounter = ctx.Agentemployers.Where(ae => ae.Ssn == trust.Ssn).Max(ae => ae.Empcounter)
}).ToList();
// Group the table data
var tblDataGrouped = trusteeTblDataUngrouped.GroupBy(x => new
{
x.FName,
x.MInital,
x.LName,
x.legalAddr,
x.mailAddr,
x.atDescr,
x.EmpStatus
});
var tblData = from trustee tblDataGrouped
join agentEmp in ctx.AgentEmployers
on new { /* HERE_1 */ } equals new { agentEmp.SSN, agentEmp.EmpCounter } into temp
from subEmployer in temp.DefaultIfEmpty
select new { /* HERE_2 */ };