Linq到实体。嵌套投影

时间:2014-01-21 21:49:14

标签: c# .net linq projection

假设我在EF模型中有两个项目可以投射到DTO之后:

public class AddressDto
{
    public int Id { get; set; }
    public string Address { get; set; }

    public static Expression<Func<Address, AddressDto>> Address2AddressDto()
    {
        return x => new AddressDto() {
            Id = x.Id,
            FullName = x.AddressLine
        };
    }
}

public class ClientDto
{
    public int Id { get; set; }
    public int FullName { get; set; }
    public AddressDto Address { get; set; }
}

如何为ClientDto创建一个投影,重新使用AddressDto的投影来转换Address中的嵌套Client?基本上我想要这样的东西:

public static Expression<Func<Client, ClientDto>> Client2ClientDto()
{
    return x => new ClientDto() {
        Id = x.Id,
        FullName = x.FullName,
        Address
           = <Apply projection AddressDto.Address2AddressDto to object x.Address>
    };
}

我知道我能做到:

public static Expression<Func<Client, ClientDto>> Client2ClientDto()
{
    return x => new ClientDto() {
        Id = x.Id,
        FullName = x.FullName,
        Address = new AddressDto() {
            Id = x.Id,
            FullName = x.AddressLine
        }
    };
}

但我想在一个地方管理AddressDto投影,而不是使用这个投影的每个地方(真实对象要复杂得多,代码重复会导致长期问题)。

在我的来电代码中,我想做类似

的事情
dbRepo.Clients.Select(Client2ClientDto())

我当前的所有尝试都以例外结束:

  

LINQ to Entities中不支持LINQ表达式节点类型“Invoke”。

2 个答案:

答案 0 :(得分:1)

你最好的选择,如果你想要遵循这种模式,可能会使用LINQKit。它会让你这样做:

public static Expression<Func<Client, ClientDto>> Client2ClientDto()
{
    var addr = AddressDto.Address2AddressDto()
    return x => new ClientDto() {
        Id = x.Id,
        FullName = x.FullName,
        Address = addr.Invoke(x)
    };
}

但你必须这样称呼它:

dbRepo.Clients.AsExpandable().Select(Client2ClientDto())

答案 1 :(得分:0)

除非您已经构建了所有投影,否则我会考虑使用AutoMapper。您可以非常轻松地创建静态映射(默认情况下它将像属性一样映射,但您也可以添加其他映射),并且可以在静态映射中定义投影:

Mapper.CreateMap<Address, AddressDto>();
Mapper.CreateMap<Client, ClientDto>();

当AutpMapper转换Client对象时,会看到已定义AddressAddressDto的地图并将使用该地图。