Let's say I have two items in EF model that could be projected to following DTOs:
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; }
}
How can I create a projection for ClientDto
reusing projection from AddressDto
to convert nested Address
in Client
? Basically I want something like:
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>
};
}
I'm aware that I can do:
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
}
};
}
But I would like to manage AddressDto
projection in one place instead of every place this projection is used (real objects are far more complicated and code duplication will cause issues in long run).
In my caller code I want to do something like
dbRepo.Clients.Select(Client2ClientDto())
All my current attempts ended up with the exception:
The LINQ expression node type 'Invoke' is not supported in LINQ to Entities.
Your best bet, if you want to follow this pattern, is probably to use LINQKit. It'll let you do this:
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)
};
}
But you'll have to call it like this:
dbRepo.Clients.AsExpandable().Select(Client2ClientDto())