I faced a problem in a project and have successfully repro'd it in a bare test project.
I have the following dtos:
public class AppUserDto
{
public int Id { get; set; }
public string Name { get; set; }
}
public class IssueDto
{
public int Id { get; set; }
public AppUserDto Owner { get; set; }
public AppUserDto Creator { get; set; }
}
The corresponding models are absolutely the same except that there are model relationships instead of DTOs (obviously).
AutoMapper config:
Mapper.CreateMap<AppUser, AppUserDto>().MaxDepth(1);
Mapper.CreateMap<Issue, IssueDto>().MaxDepth(1);
The simplest of queries:
var i = context.Issues.ProjectTo<IssueDto>().FirstOrDefault();
This always throws a NotSupportedException
:
The type 'AppUserDto' appears in two structurally incompatible initializations within a single LINQ to Entities query. A type can be initialized in two places in the same query, but only if the same properties are set in both places and those properties are set in the same order.
This is a problem from automapper of course.
Now I tried the following:
Mapper.CreateMap<AppUser, AppUserDto>().MaxDepth(1)
.ProjectUsing(u => new AppUserDto
{
Id = u == null ? -1 : u.Id,
Name = u == null ? null : u.Name,
});
This makes queries like context.Issues.ProjectTo<IssueDto>()...
succeed. But this in turns make direct mappings for AppUser
result in null values (or 0 for Id). So context.Users.ProjectTo<AppUserDto>().FirstOrDefault()
(or even Mapper.Map<AppUserDto>(context.Users.FirstOrDefault())
) always return an AppUserDto
with default values for its props.
So, how to make multiple nested dto objects of the same type in the same base dto work without sacrificing direct mappings for said dto object?
Solving the problem with ProjectUsing (if we can make direct mappings work at the same time) is less than ideal, but if it's the only way to go I can manage.
There is a bug most likely, this is the github issue for anyone who's interested.
The culprit was actually the MaxDepth
call itself. It may not seem so but sticking MaxDepth
on every mapping might produce side effects as I've seen.
As it turns out, I don't have recursion on my Dtos at all (and that's what MaxDepth
is for). So just removing all MaxDepth
calls will solve this without needing ProjectUsing
.
This has been cleared out here.