Pergunta

Dado um funcionário, como posso construir uma consulta LINQ para SQL para encontrar todos os ancestrais do funcionário? Cada funcionário tem um supervisorid associado (veja abaixo).

Por exemplo, uma consulta dos ancestrais para o Funcionário 6 (Frank Black) deve devolver Jane Doe, Bob Smith, Joe Bloggs e Head Honcho.

Se necessário, posso armazenar em cache a lista de todos os funcionários para melhorar o desempenho.

ATUALIZAR:

Eu criei o seguinte método bruto para realizar a tarefa. Ele atravessa o relacionamento do funcionário.Supervisor até o nó raiz. No entanto, isso emitirá uma chamada de banco de dados para cada funcionário. Alguém tem um método mais sucinto ou mais performante? Obrigado.

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;
}
Foi útil?

Solução

Primeiro de tudo, você pode usar as consultas hierárquicas no meu Projeto Métodos de Extensão Linq. Eu acho que pode ajudar a simplificar seu código.

O problema aqui é que isso criará uma chamada de banco de dados para cada nó na hierarquia. No caso do seu exemplo, você terá 5 viagens de ida e volta ao banco de dados.

Eu seguia um caminho diferente e criaria um procedimento armazenado para fazer isso por mim e devolver todo o conjunto de Employee objetos. Como você está desconectando os objetos antes de devolvê-los (descartando o contexto), você pode simplesmente criar um novo objeto a partir do conjunto de resultados do procedimento armazenado.

Outras dicas

Uma solução simples que evita carregar toda a tabela de funcionários (mas tem uma profundidade limitada de travessia) é ...

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

Em última análise, você deve usar um Expressão comum da tabela Para achatar a hierarquia, mas o LINQ para o SQL atualmente não suporta isso. Você pode procurar escrever seu próprio método de extensão (como o da Biblioteca de Omer, mas usando o iQueryable em vez de ienumerable para oferecer suporte à execução do lado do servidor).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top