1

I have a recursive database table and hierarchical view through all table data

CREATE VIEW dbo.vw_hierarchicalView
AS
    WITH hView (Id,
                    IdParent,
                    Level)
    AS
    (
        SELECT tableParent.Id,
               tableParent.IdParent,
               1 AS Level
        FROM dbo.vw_ComplaintWithStatus tableParent
        WHERE tableParent.IdParent IS NULL
        UNION ALL SELECT tableChild.Id,
                         tableChild.IdParent,
                         hw.level + 1 AS  Level
                 FROM dbo.vw_ComplaintWithStatus tableChild
                      INNER JOIN hView hw ON  tableChild.IdParent = hw.Id
    )
    SELECT final.Id,
           final.IdParent,
           ISNULL(final.Level, 1) AS Level
    FROM hView final

When I do query for all data, all tree is right.

SELECT * FROM dbo.vw_hierarchicalView hw ORDER BY hw.Level, hw.Id

But, if i want to select full tree only for one id, query show me only first row with specified id

SELECT * FROM dbo.vw_hierarchicalView hw WHERE hw.Id = 5 ORDER BY hw.Level, hw.Id

I want to use this in my application to find all children records in tree using Entity Framework.

Logic of application returns me some record and need to find:

  1. first direct children records only
  2. all children records (for showing tree in web page)

I class to select from view to a stored procedure with Id as argument of this procedure and replace condition WHERE tableParent.IdParent IS NULL on WHERE tableParent.Id = @id. This solution works well, but ...

I rather don't want to use a stored procedure.

Is any way how to solve this without database functions or procedures?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Davecz
  • 1,199
  • 3
  • 19
  • 43

1 Answers1

1

You could use table valued function:

CREATE FUNCTION my_func(@root_id INT)
RETURNS TABLE
AS
RETURN
WITH hView (Id,IdParent,Level) AS
    (
        SELECT tableParent.Id,
               tableParent.IdParent,
               1 AS Level
        FROM dbo.vw_ComplaintWithStatus tableParent
        WHERE (tableParent.IdParent IS NULL  AND @root_id IS NULL)
           OR Id = @root_id
        UNION ALL SELECT tableChild.Id,
                         tableChild.IdParent,
                         hw.level + 1 AS  Level
                 FROM dbo.vw_ComplaintWithStatus tableChild
                      INNER JOIN hView hw ON  tableChild.IdParent = hw.Id
    )
    SELECT final.Id,
           final.IdParent,
           ISNULL(final.Level, 1) AS Level
    FROM hView final;

Call:

SELECT * FROM dbo.my_func(NULL) hw ORDER BY hw.Level, hw.Id;
--
SELECT * FROM dbo.my_func(5) hw ORDER BY hw.Level, hw.Id;
Lukasz Szozda
  • 162,964
  • 23
  • 234
  • 275
  • i have did it through stored procedure now. I am interest about solution without function or procedures. If it is possible... – Davecz Jun 22 '19 at 15:27
  • @Davecz TVP Function is basically parametrized view and it's a proper way of handling such scenarios [Can we pass parameters to a view in SQL?](https://stackoverflow.com/questions/1687279/can-we-pass-parameters-to-a-view-in-sql) – Lukasz Szozda Jun 22 '19 at 15:28
  • @Davecz The greatest advantage of TVP Function over Stored Procedure is that you could easily combine it with other queries(here is simply part of FROM clause), You could still add additional WHERE conditions or wrap it with subquery. – Lukasz Szozda Jun 22 '19 at 15:30
  • i know that, but is it possible to call function in where conditions in entity framework? for example var data = from d in DbSet where DataContext.MyFunction(d.Id) select d; I am not sure – Davecz Jun 22 '19 at 15:37
  • @Davecz I am not an EF's expert but I suppose there should be annotation on entity class level like `query/...`. At least sth like that is possible with hibernate. You should start a new question how to map EntityFramework to SQL function call – Lukasz Szozda Jun 22 '19 at 15:39
  • It is not necessary to ask a new question :-D . I rewrite it to function by your advice and I will make two questions to database for quick solution now a maybe later i will be optimalize... Thanks – Davecz Jun 22 '19 at 15:50