Linq to Sql - Иерархический запрос для поиска предков

StackOverflow https://stackoverflow.com/questions/236575

  •  04-07-2019
  •  | 
  •  

Вопрос

Учитывая EmployeeID, как я могу создать запрос Linq to Sql, чтобы найти всех предков employee?С каждым идентификатором сотрудника связан идентификатор супервайзера (см. Ниже).

Например, запрос предков для EmployeeID 6 (Фрэнк Блэк) должен возвращать Jane Doe, Bob Smith, Joe Bloggs и Head Honcho.

При необходимости я могу кэшировать список всех сотрудников, чтобы повысить производительность.

Обновить:

Я создал следующий грубый метод для выполнения этой задачи.Он проходит через отношения сотрудник.Супервайзер вплоть до корневого узла.Однако при этом будет выполнен один вызов базы данных для каждого сотрудника.У кого-нибудь есть более краткий или более эффективный метод?Спасибо.

private List<Employee> GetAncestors(int EmployeeId)
{
    List<Employee> emps = new List<Employee>();
    using (L2STestDataContext dc = new L2STestDataContext())
    {
        Employee emp = dc.Employees.FirstOrDefault(p => p.EmployeeId == EmployeeId);
        if (emp != null)
        {
            while (emp.Supervisor != null)
            {
                emps.Add(emp.Supervisor);
                emp = emp.Supervisor;
            }
        }
    }
    return emps;
}
Это было полезно?

Решение

Прежде всего, вы можете использовать иерархические запросы в моем Проект Методов расширения LINQ.Я думаю, это может помочь упростить ваш код.

Проблема здесь в том, что это создаст вызов базы данных для каждого узла в иерархии.В случае с вашим примером у вас будет 5 обратных обращений к базе данных.

Я бы пошел другим путем и создал хранимую процедуру, которая сделала бы это за меня, и вернул бы весь набор Employee Объекты.Поскольку вы отключаете объекты перед их возвратом (удаляя контекст), вы могли бы просто создать новый объект из результирующего набора хранимой процедуры.

Другие советы

Простым решением, которое позволяет избежать загрузки всей таблицы Employee (но имеет ограниченную глубину обхода), является...

var emps = dc.Employees.Where(e => (e.EmployeeId == EmployeeId) ||
                                   (e.SupervisorId == EmployeeId) ||
                                   (e.Supervisor.SupervisorId == EmployeeId) ||
                                   (e.Supervisor.Supervisor.SupervisorId == EmployeeId) ||
                                   ...);

В конечном счете, вы должны использовать общее табличное выражение чтобы сгладить иерархию, но LINQ to SQL в настоящее время не поддерживает это.Вы могли бы подумать о написании своего собственного метода расширения (например, в библиотеке Omer, но с использованием IQueryable вместо IEnumerable для поддержки выполнения на стороне сервера).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top