2009-12-12 2 views
0

У меня есть слой данных linq-to-sql, в котором есть 2 таблицы. «Родитель» и «Ребенок». Есть отношения между Child and Parent (так что у родителя много детей и т. Д.) Родитель может также иметь много родителей (когда дети растут и сами становятся родителями).Эффективный выбор дерева в Linq-To-Sql

Я хочу отобразить эту иерархию для пользователя, но я не уверен, как это сделать эффективно.

Неэффективное подход сделать:

foreach(Parent in db.Parents) 
{ 
    output(Parent.Parents) 
    output(Parent.Children) 
} 

Но это порождает дб туда и обратно два раза для каждой итерации цикла (Ик !!), если это большая семья, это будет ДЕЙСТВИТЕЛЬНО дорого.

Есть ли лучший способ? (бог, я надеюсь, что так!)

ответ

1

Я бы предложил загрузить всю коллекцию, которую вы хотите передать в пользовательский интерфейс. Если метод генерации родительской коллекции parent -> parent является рекурсивным (как представляется, он может быть), используйте код L2S для выбора элементов рекурсивным образом. Таким образом, повторение окончательного набора результатов в пользовательском интерфейсе не приведет к неэффективности команд SQL.

Пример:
я не знаю, если это лучший/кратчайший/чистый способ сделать это, но, надеюсь, вы получите идею. static функции coz его консольное приложение.

class Program 
{ 
    static void Main(string[] args) 
    { 
     foreach (ParentDTO p in GetParents().ToList()) 
     { 
      if (p.Parent == null) 
       Console.WriteLine(String.Format("{0} ({1})", 
        p.Name, p.ID.ToString())); 
      else 
       Console.WriteLine(String.Format("{0} ({1}){2}", 
        p.Name, p.ID.ToString(), "\r\n\t-" + p.Parent.Name)); 
     } 

     Console.ReadKey(); 
    } 

    private static IQueryable<ParentDTO> GetParents() 
    { 
     var db = new DataClasses1DataContext(); 
     db.Log = new DebuggerWriter(); 

     return from p in db.Parents 
       let parentParent = GetParentOfParent(p.ParentID) 
       select new ParentDTO 
       { 
        ID = p.ID, 
        Name = p.Name, 
        Parent = parentParent 
       }; 
    } 

    private static ParentDTO GetParentOfParent(int? childParentID) 
    { 
     if (childParentID.HasValue) 
      return GetParents().Single(p => p.ID == childParentID); 
     else 
      return null; 
    } 
} 

данные Таблица:

ID ParentID Имя
1 NULL Билл
2 8 Мэри
3 1 Гэри
4 1 Милла
5 NULL Сью
6 NULL Фред
7 NULL Marg
8 7 Хиллари

Выход:

Билл (1)
Мери (2)
-Hillary
Гэри (3)
-Билль
Милла (4)
-Билль
Сью (5)
Fred (6)
Mar г (7)
Хиллари (8)
-Marg

(в отступом/дефис названия соответствующих родителей)

Это выход отладчик от L2S постоянного тока Log:

SELECT [t0]. [ID], [t0]. [ParentID], [t0].[Имя]
ОТ [DBO] [Родитель] AS [t0]
ГДЕ ([t0] [ID].) = @ Р0
- @ р0:. Входной Int (размер = 0; Prec = 0; Масштаб = 0) [8]
- Контекст: SqlProvider (SQL2005) Модель: AttributedMetaModel Сложение: 3.5.30729.1

SELECT [t0] [ID], [t0] [ParentID], [t0]... [Имя]
ОТ [DBO] [родитель] AS [t0]
ГДЕ ([t0] [ID].) = @ р0
- @ р0:. Входной Int (размер = 0; Prec = 0; Шкала = 0) [7]
- Контекст: SqlProvider (Sql2005) Модель: Attri butedMetaModel Строение: 3.5.30729.1

SELECT [t0] [ID], [t0] [ParentID], [t0] [Имя]
ОТ [DBO] [Родитель] AS [t0]
.... ГДЕ ([t0]. [ID]) = @ p0
- @ p0: Input Int (Размер = 0; Prec = 0; Масштаб = 0) [1]
- Контекст: SqlProvider (SQL2005) Модель: AttributedMetaModel Сложение: 3.5.30729.1

SELECT [t0] [ID], [t0] [ParentID], [t0]... [Имя]
ОТ [DBO] [родитель] AS [t0]
ГДЕ ([t0] [ID].) = @ р0
- @ р0:. Входной Int (размер = 0; Prec = 0; Масштаб = 0) [1]
- Контекст: SqlProvider (SQL2005) Модель: AttributedMetaModel Сложение: 3.5.30729.1

SELECT [t0] [ID], [t0] [ParentID], [t0]... [Имя]
FROM [dbo]. [Paren t] AS [t0]
ГДЕ ([t0]. [ID]) = @ p0
- @ p0: Input Int (Размер = 0; Prec = 0; Масштаб = 0) [7]
- Контекст: SqlProvider (SQL2005) Модель: AttributedMetaModel Сложение: 3.5.30729.1

..all из которых стреляли в один присест на .ToList(); линии (как и ожидалось).

Надеюсь, это полезно.

+0

Это звучит очень хорошо ... какой код L2s доступен для выбора элементов рекурсивным образом? – Paul

 Смежные вопросы

  • Нет связанных вопросов^_^