我在一个项目中遇到了一个问题,并在一个裸测试项目中成功地重新编写了它.
我有以下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; }
}
除了有模型关系而不是DTO(显然)之外,相应的模型是完全相同的.
AutoMapper配置:
Mapper.CreateMap<AppUser, AppUserDto>().MaxDepth(1);
Mapper.CreateMap<Issue, IssueDto>().MaxDepth(1);
最简单的查询:
var i = context.Issues.ProjectTo<IssueDto>().FirstOrDefault();
这总是抛出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.
这当然是来自automapper的一个问题.
现在我尝试了以下内容:
Mapper.CreateMap<AppUser, AppUserDto>().MaxDepth(1)
.ProjectUsing(u => new AppUserDto
{
Id = u == null ? -1 : u.Id,
Name = u == null ? null : u.Name,
});
这使得像context.Issues.ProjectTo< IssueDto>()…这样的查询成功.但这反过来使得AppUser的直接映射导致空值(或Id为0).因此context.Users.ProjectTo< AppUserDto>().FirstOrDefault()(甚至Mapper.Map< AppUserDto>(context.Users.FirstOrDefault()))总是返回一个AppUserDto,其默认值为其props.
那么,如何在同一个基础dto中创建相同类型的多个嵌套dto对象,而不牺牲所述dto对象的直接映射?
使用ProjectUsing解决问题(如果我们可以让直接映射同时工作)不太理想,但如果这是唯一可行的方法,我可以管理.
编辑:
最有可能是一个bug,对于任何有兴趣的人来说都是this is the github issue.
解决方法:
罪魁祸首实际上是MaxDepth电话本身.它可能看起来不是这样,但在每个映射上粘贴MaxDepth可能会产生副作用,正如我所见.
事实证明,我根本没有对我的Dtos进行递归(这就是MaxDepth的用途).因此,只需删除所有MaxDepth调用即可解决此问题而无需ProjectUsing.
这已经被清除了here.