【问题标题】:Linq to entity. Nested projectionLinq 到实体。嵌套投影
【发布时间】:2014-01-21 21:49:13
【问题描述】:

假设我在 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”。

【问题讨论】:

    标签: c# .net linq projection


    【解决方案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())
    

    【讨论】:

      【解决方案2】:

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

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

      当 AutpMapper 去转换 Client 对象时,它会看到定义了一个从 AddressAddressDto 的映射并将使用它。

      【讨论】:

      • 不,但如果你先对对象进行水合然后映射它就可以了。
      • 好吧,如果我需要先实现它,那么我可以在有问题的行上使用诸如 AddressDto.Address2AddressDto().Compile()(x.Address) 之类的东西来实现相同的目标。我只是希望有一种方法可以在那个时候仍然没有物化数据。
      猜你喜欢
      • 1970-01-01
      • 2020-11-19
      • 2019-09-07
      • 1970-01-01
      • 1970-01-01
      • 2015-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多