Linq to Entity. 嵌套投影

3

假设我在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; }
}

我该如何创建一个投影,以重用来自 AddressDto 的投影,将嵌套在 Client 中的 Address 转换为 ClientDto?基本上我想要这样的东西:
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表达式节点类型“Invoke”在LINQ to Entities中不受支持。

2个回答

2

如果您想要遵循这种模式,最好的选择可能是使用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())

0

如果你还没有构建好所有的投影,我建议使用AutoMapper。你可以很容易地创建一个静态映射(默认情况下它将像属性一样进行映射,但你也可以添加其他映射),并且可以在静态映射中定义投影:

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

当 AutoMapper 转换 Client 对象时,它会发现有一个从 Address 到 AddressDto 的映射定义,并使用它。

不过,如果您先将对象进行hydrate(注水)处理,然后再进行映射,就可以实现。 - D Stanley
1
如果我需要先实现它,那么我可以在相关行使用类似AddressDto.Address2AddressDto().Compile()(x.Address)的方法来实现相同的效果。我只是希望在那个时候仍然有一种方式可以不实现数据。 - AlexanderM
不不不。请不要使用AutoMapper,这是一条很滑的坡,最终会导致代码库难以调试和理解。只需编写自定义映射逻辑,这并不难。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接