views:

90

answers:

1

I have successfully simulated an Oracle CONNECT BY statement in SQL Server 2008 by following these 2 previous answers here and here and adjusting to get the results I need. But how do I do this in LINQ?

Here is an example of what I am doing using a dummy database:

CREATE TABLE Employee(
 EmployeeID INT IDENTITY(1,1) PRIMARY KEY,
 Department INT NOT NULL,
 EmployeeName VARCHAR(40) NOT NULL,
 PeckingOrder INT NOT NULL,
 HigherDepartment INT NULL)

INSERT INTO Employee (Department,EmployeeName,PeckingOrder,HigherDepartment)
VALUES (1,'Bart',1,NULL),(2,'Homer',1,1),(2,'Marge',2,NULL),
       (3,'Lisa',1,2),(3,'Maggie',2,2),(3,'Santas Helper',3,1)

EmployeeID Department EmployeeName PeckingOrder HigherDepartment
    1            1     Bart            1             NULL
    2            2     Homer           1              1 
    3            2     Marge           2             NULL
    4            3     Lisa            1              2
    5            3     Maggie          2              2
    6            3     Santas Helper   3              1

and this is the SQL used to return the heirachy:

WITH n(level, PeckingOrder, Department, EmployeeName, HigherDepartment) AS 
    (SELECT 1, PeckingOrder, Department, EmployeeName, HigherDepartment
    FROM Test.dbo.Employee
    WHERE Department = 3
        UNION ALL
   SELECT n.level + 1, nplus1.PeckingOrder, nplus1.Department, nplus1.EmployeeName, nplus1.HigherDepartment 
   FROM Test.dbo.Employee as nplus1
   JOIN n ON n.HigherDepartment = nplus1.Department)
SELECT MAX(level) AS level, PeckingOrder, Department, EmployeeName, HigherDepartment   
FROM n
GROUP BY PeckingOrder, Department, EmployeeName, HigherDepartment
ORDER BY MAX(level) DESC, PeckingOrder ASC

level PeckingOrder Department EmployeeName HigherDepartment
  3         1           1           Bart             NULL
  2         1           2           Homer              1
  2         2           2           Marge             NULL
  1         1           3           Lisa               2
  1         2           3           Maggie             2
  1         3           3           Santas Helper      1
+1  A: 

You could use ExecuteQuery:

class YourRow
{
    public int level {get; set;}
    public int PeckingOrder {get; set;}
    ...
}

using (var db = new LinqDataContext())
{
    var list = db.ExecuteQuery<YourRow>(
@"
WITH n(level, PeckingOrder, Department, EmployeeName, HigherDepartment) AS 
    (SELECT 1, PeckingOrder, Department, EmployeeName, HigherDepartment
...
";
}

Or perhaps better, create a view that contains the query, and use LINQ to read from the view.

Andomar
ExecuteQuery is how I am doing it at the moment, but I was hoping to query the tables directly with linq rather than sql. Prefer to use linq if possible rather than creating a view specifically for this.
JumpingJezza
@JumpingJezza: Linq2Sql generates SQL using expression trees. Not sure if it can generate recursive SQL, but I am confident that doing so would be more complex than writing it in SQL :)
Andomar
Actually I don't think I can use a view as I need that parameter in the middle of the query (Department = 3), but maybe I can use a function. Easy fix is to leave it running executequery :) Syntax I'm using is slightly different as I need it as a list: List<YourRow> result = context.ExecuteQuery<YourRow>("WITH ... Department = {0} ...", DepartmentID).AsQueryable().ToList();
JumpingJezza