Combinaison de clauses de sélection dans linq avec des entités de types anonymes

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

Question

Comment puis-je combiner la clause select dans linq avec des entités afin de projeter dans un type anonyme?
Supposons que j'ai ces entités:

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; }
}

Parfois, je n'ai besoin que de demander quelques propriétés de ma classe Person:

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

Et je dois également demander les mêmes propriétés de ma classe Employé, plus les propriétés spécifiques:

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
});

Est-il possible avec des manipulations d'expression-arbre ( ou une autre solution ) de combiner deux clauses de sélection afin de ne pas dupliquer toutes les clauses de sélection de mon entité Personne?

Quelque chose comme ca:

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"
// }

Réponse acceptée

Non, il n'y a aucun moyen de faire exactement ce que vous demandez. Le problème est que chaque type anonyme doit être créé au moment de la compilation, mais que les arbres d'expression fonctionnent au moment de l'exécution.

Je peux voir deux façons de contourner ce problème:

  1. Votre type anonyme pour Employee aurait une propriété appelée quelque chose comme PersonData , qui contiendrait le type anonyme avec les informations de Person .
  2. Vous PersonData des types normaux comme PersonData et EmployeeData (qui hérite de PersonData ). Chaque type pourrait vous donner une expression pour le créer et l'expression de EmployeeData serait calculée en fonction de l'expression de PersonData .

Dans les deux cas, vous aurez besoin d'une plomberie d'arbres d'expression, mais cela ne devrait pas être difficile.




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi