Один из способов сделать это - использовать рекурсивный cte, который также будет сохранять корневой узел каждой рекурсии, а затем запрашивать этот cte на основе корня нужного узла.
Сначала создайте и заполните образец таблицы: ( Пожалуйста, сохраните нам этот шаг в ваших будущих вопросах)
DECLARE @T AS TABLE
(
NodeId int,
Parent int
);
INSERT INTO @T (NodeId, Parent) VALUES
(1 , 0),
(3 , 1),
(7 , 3),
(8 , 3),
(4 , 1),
(9 , 4),
(10, 4),
(2 , 0),
(5 , 2),
(11, 5),
(12, 5),
(6 , 2),
(13, 6);
Рекурсивный cte:
WITH CTE AS
(
SELECT NodeId, Parent, NodeId As Root
FROM @T
WHERE Parent = 0
UNION ALL
SELECT t.NodeId, t.Parent, Root
FROM @T As t
JOIN CTE
ON t.Parent = CTE.NodeId
)
Запрос:
SELECT NodeId, Parent
FROM CTE
WHERE Root = (SELECT Root FROM CTE WHERE NodeId = 4)
Результаты:
NodeId Parent
1 0
3 1
4 1
9 4
10 4
7 3
8 3
Если Ваш UserControl появляется на каждой странице, то один способ обратиться к этому состоял бы в том, чтобы использовать основной контроллер, от которого все Ваши контроллеры получают и генерируют ViewData для UserControl путем переопределения метода OnActionExecuting и помещения логики там. Если Ваш UserControl является менее распространяющимся, но все еще часто используемый всюду по сайту, Вы могли бы расширить ActionFilterAttribute и иметь Ваш фильтр, генерируют необходимые данные. Этот атрибут мог использоваться для украшения контроллеров или действий, которые генерируют представления, которые используют UserControl.
Я предполагаю во всем этом, что данные для UserControl независимы от вызываемого действия. Если существует зависимость, вероятно, лучше продвинуть логику в класс (или классы, возможно, с помощью Стратегии) и сделать поколение данных явным в каждом действии или контроллере (через переопределение OnActionExecuting).
Можно также рассмотреть помещение образцовых классов в иерархии. Высшее сословие (или одно из высших сословий) будет содержать данные, необходимые для Ваших распространяющихся пользовательских элементов управления. Затем можно загрузить эти наиболее часто используемые данные в основном классе контроллера.
В качестве альтернативы в ASP.NET MVC 2 теперь можно использовать RenderAction для вызова совершенно нового действия контроллера, которое может получать данные. Это делает ваш код более модульным и становится более понятным, откуда берутся данные.