将linq中的select子句与具有匿名类型的实体组合

时间:2013-06-21 12:59:12

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

如何将linq中的select子句与实体结合起来以投射到匿名类型?
假设我有这些实体:

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

有时我只需要请求Person类的少数属性:

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

我还需要请求我的Employee类的相同属性以及特定属性:

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

表达式树操作(或其他解决方案)是否可以组合两个select子句,以便不复制Person实体中的所有select子句?

类似的东西:

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

1 个答案:

答案 0 :(得分:2)

不,没有办法完全按照你的要求去做。问题是必须在编译时创建每个匿名类型,但表达式树在运行时工作。

我可以通过两种方式解决这个问题:

  1. Employee的匿名类型会有一个名为PersonData的属性,其中包含匿名类型,其中包含来自Person的信息。
  2. 您可以创建普通类型,例如PersonDataEmployeeData(继承自PersonData)。每种类型都可以为您创建表达式,EmployeeData的表达式将根据PersonData的表达式计算。
  3. 在这两种情况下,你都需要一些表达树管道,但它不应该那么难。