假设我在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”。
答案 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
对象时,会看到已定义Address
到AddressDto
的地图并将使用该地图。