Combine cláusulas selectas en linq a entidades con tipos anónimos

.net anonymous-types c# expression-trees linq-to-entities

Pregunta

¿Cómo puedo combinar una cláusula de selección en linq con entidades para proyectar en un tipo anónimo?
Supongamos que tengo estas entidades:

public class Address
{
    public string City { get; set; }
    public int ZipCode { get; set; }
    //other properties
}

public class Person 
{
    public string Name { get; set; }
    public Address Address { get; set; }
    //a LOT of other properties
}

//extend person class with employee specific properties 
public class Employee : Person
{
    public double Salary { get; set; }
    public Person Manager { get; set; }
}

A veces solo necesito solicitar algunas propiedades de mi clase Person:

Context.Persons.Where(...).Select(p => new 
{
    p.Name,
    PersonCity = p.Address.City,
    //other needed properties
});

Y también necesito solicitar las mismas propiedades de mi clase de empleado más las propiedades específicas:

Context.Employees.OfType<Employee>().Where(...).Select(e => new
{
    e.Salary,
    ManagerName = e.Manager.Name,
    e.Name,
    PersonCity = e.City.Name,
    //other needed properties identical as the previous select with Person entity
});

¿Es posible con las manipulaciones del árbol de expresión ( u otra solución ) combinar dos cláusulas de selección para no duplicar toda la cláusula de selección de la entidad de mi persona?

Algo como eso:

var personSelect = p => new {
    p.Name,
    PersonCity = p.Address.City,
    //other needed properties
};

var employeeSelect = personSelect.Combine(e => new {
    e.Salary,
    ManagerName = e.Manager.Name
});

context.Employees.OfType<Employee>().Where(...).Select(employeeSelect).FirstOrDefault();
// returns an anonymous object 
// {
//     Name = "Joachim",
//     PersonCity = "Lyon",
//     <other Person properties>
//     Salary = 65432.10,
//     ManagerName = "Samuel"
// }

Respuesta aceptada

No, no hay manera de hacer exactamente lo que estás pidiendo. El problema es que cada tipo anónimo debe crearse en tiempo de compilación, pero los árboles de expresión funcionan en tiempo de ejecución.

Puedo ver dos maneras de evitar eso:

  1. Su tipo anónimo para Employee tendría una propiedad llamada algo como PersonData , que contendría el tipo anónimo con la información de Person .
  2. PersonData tipos normales como PersonData y EmployeeData (que se heredan de PersonData ). Cada tipo podría darle una expresión para crearla y la expresión de EmployeeData se computaría en función de la expresión de PersonData .

En ambos casos, necesitaría plomería de algunos árboles de expresión, pero no debería ser difícil hacer eso.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow