.net core &引用;序列不包含匹配元素“;同时使用OData&;扩展子导航属性;汽车制造商

.net core &引用;序列不包含匹配元素“;同时使用OData&;扩展子导航属性;汽车制造商,.net-core,odata,automapper,entity-framework-core-2.1,.net Core,Odata,Automapper,Entity Framework Core 2.1,尝试使用以下查询扩展导航属性时出现异常“Sequence contains no matching element:?$expand=roles。没有$expand关键字的请求有效。DTO对象通过非常简单的映射配置从AutoMapper接收 请参阅有关资料来源: 实体框架实体: 公共类用户{ 公共字符串Id{get;set;} 公共字符串用户名{get;set;} 公共字符串电子邮件{get;set;} 公共虚拟ICollection用户角色{get;set;} } 公共阶级角色{ 公共字符串

尝试使用以下查询扩展导航属性时出现异常“Sequence contains no matching element:?$expand=roles。没有$expand关键字的请求有效。DTO对象通过非常简单的映射配置从
AutoMapper
接收

请参阅有关资料来源:


实体框架实体:

公共类用户{
公共字符串Id{get;set;}
公共字符串用户名{get;set;}
公共字符串电子邮件{get;set;}
公共虚拟ICollection用户角色{get;set;}
}
公共阶级角色{
公共字符串Id{get;set;}
公共字符串名称{get;set;}
}
公共类用户角色{
公共字符串用户标识{get;set;}
公共字符串RoleId{get;set;}
}
DTO型号:

公共类用户模型{
公共字符串Id{get;set;}
公共字符串用户名{get;set;}
公共字符串电子邮件{get;set;}
公共IEnumerable角色{get;set;}
}
公共类角色模型
{
公共字符串Id{get;set;}
公共字符串名称{get;set;}
}
AutoMapper
配置:

CreateMap()
.ForMember(x=>x.Id,x=>x.MapFrom(m=>m.UserId))
.ForMember(x=>x.Name,x=>x.MapFrom(m=>m.Role.Name));
CreateMap()
.FormMember(dest=>dest.Roles,opts=>opts.MapFrom(src=>src.UserRoles))
.ReverseMap()
.ForMember(dest=>dest.UserRoles,o=>o.Ignore());
控制器动作方法:

[HttpGet]
[启用查询]
公共IQueryable Get()=>
_userManager.Users.ProjectTo(_mapper.ConfigurationProvider);
实际上,
Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.CorrelatedCollectionOptimizingVisitor
在试图查找由
自动映射程序生成的表达式中的WHERE子句时引发了异常。这一行:

var originalCorrelationPredicate=collectionQueryModel.body子句
第()类
.Single(c=>c.谓词为NullSafequalExpression);
如果我将
AutoMapper
的配置更改为以下内容,则不会引发异常,但会对每个用户记录分别执行角色子查询:

CreateMap()
.FormMember(目标=>目标角色,选项=>
opts.MapFrom(src=>
src.UserRoles.Select(ur=>newrolemodel{
Id=ur.UserId,
Name=ur.Role.Name
})))
.ReverseMap()
.ForMember(dest=>dest.UserRoles,o=>o.Ignore());
我检查了另一个想法:如果我将action方法更改为调用ProjectTo()结果上的ToList()方法,那么在DB上只执行两个查询,并且不会发生错误。这就是为什么我认为在同时使用OData和AutoMapper时出现错误的原因

我做错了什么


增加:

我检查了@Lucian建议的执行计划,发现AutoMapper生成的表达式和另一个手工编写的表达式之间的唯一区别是子查询调用

手写变体(按其应有的方式工作):

。。。。。。。
角色=.Call System.Linq.Enumerable.Select(
$x.UserRoles,
兰姆达先生
#Lambda2),
.......
由AutoMapper生成:

.......
Roles = .Call System.Linq.Enumerable.ToList(.Call 
     System.Linq.Enumerable.Select(
           $x.UserRoles,
           .Lambda 
#Lambda2<System.Func`2[Test.Data.UserRole,Test.Models.RoleModel]>)),
.......
。。。。。。。
角色=.Call System.Linq.Enumerable.ToList(.Call)
System.Linq.Enumerable.Select(
$x.UserRoles,
兰姆达先生
#Lambda2),
.......

有人知道如何强制
AutoMapper
不生成对
ToList()
的调用吗?

检查。使用执行计划,您可以在不使用AM的情况下编写该查询。这可能是EF的核心问题。@LucianBargaoanu,谢谢你的想法。我已经在帖子中添加了调查结果。对我来说,这看起来像是EF的核心问题。解决方法谢谢你们的链接
.......
Roles = .Call System.Linq.Enumerable.ToList(.Call 
     System.Linq.Enumerable.Select(
           $x.UserRoles,
           .Lambda 
#Lambda2<System.Func`2[Test.Data.UserRole,Test.Models.RoleModel]>)),
.......