I'm trying to use automapper to pull in a relationship's collection and convert to a dictionary, but I'm struggling with syntax. I have these two entities:
class Station {
public int Id { get; set; }
public string Name { get; set; }
}
class Client {
public virtual ICollection<Station> Station { get; set; } = new List<Station>();
}
I want to write the results into a DTO:
class ClientDTO {
public required IDictionary<string, int> Stations { get; init; }
}
Obviously there are other properties in all of them. I tried to use these maps:
CreateMap<ICollection<Station>, IDictionary<string, int>>()
.ConstructUsing(stations => stations
.Where(s => s.DeletedUtc == null)
.ToDictionary(s => s.Name, s => s.Id));
CreateMap<Client, ClientDTO>()
.ForMember(x => x.Stations, x => x.MapFrom(y => y.Station));
It's not able to create the projection though, and gets this exception:
System.InvalidCastException: Unable to cast object of type 'System.Linq.Expressions.MethodCallExpression3' to type 'System.Linq.Expressions.NewExpression'.
at AutoMapper.QueryableExtensions.Impl.ProjectionBuilder.<>c__DisplayClass8_0.g__CreateDestination|3().
at AutoMapper.QueryableExtensions.Impl.ProjectionBuilder.CreateProjectionCore(ProjectionRequest request, Expression instanceParameter, TypeMap typeMap, LetPropertyMaps letPropertyMaps)
Is it possible to do this with a single projection, or do I need to load the ClientDTO
without the stations, and then make a second query to pull in the stations and assign them? It's working like the below, I was just hoping there were a way to do it as a single call.
var clients = await context.Client
.AsNoTracking()
.Where(x => x.DeletedUtc == null)
.OrderBy(x => x.Name)
.ProjectTo<ClientDTO>(mapper.ConfigurationProvider)
.ToArrayAsync(cancellationToken);
var stations = await context.Station
.AsNoTracking()
.Where(x => x.DeletedUtc == null)
.GroupBy(x => x.ClientId)
.ToDictionaryAsync(x => x.Key, x => x.ToDictionary(y => y.Name, y => y.Id), cancellationToken);
foreach (var client in clients)
if (stations.TryGetValue(client.Id, out var dict))
client.Stations = dict;