1

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 */ };
Alex
  • 4,885
  • 3
  • 19
  • 39
jthomas
  • 65
  • 6
  • 1
    It helps to know the correct terminology: `agent` is an *alias* for the *derived table*. Reading about derived tables will help you understand how this query works. Please show your attempt at a conversion. – madreflection Jun 24 '20 at 18:17
  • @madreflection I've updated the post with my attempt at a solution. Thanks for the tip on derived tables, I will do some research on that – jthomas Jun 24 '20 at 19:01
  • 1
    Perhaps my [SQL to LINQ Recipe](https://stackoverflow.com/questions/49245160/sql-to-linq-with-multiple-join-count-and-left-join/49245786#49245786) might help you. For example, I would definitely create the derived table sub-query as a separate LINQ query variable, then use it in the outer query. – NetMage Jun 24 '20 at 20:56

0 Answers0