ExplicitExpansion()导致OData扩展无法正常工作 [英] ExplicitExpansion() cause OData expand not work
问题描述
使用ExplicitExpansion()时,Odata扩展不起作用. 我的DTo和EF模型可以在下面的链接中找到. 使用Odata基于EF查询DTO
When using ExplicitExpansion() Odata expand does not work. My DTo and EF Models can be found below link. Querying DTOs based on EF using Odata
我的Automapper类:
My Automapper class:
public class AutoMapperProfile : Profile
{
public AutoMapperProfile()
{
CreateMap<ClientRef, ClientContract>().
ForMember(dest => dest.ValidFrom,
opt =>
{
opt.MapFrom(y => y.Clients.FirstOrDefault(x => x.ValidFrom <= DateTime.Now && x.ValidTo > DateTime.Now).ValidFrom);
}).
ForMember(dest => dest.ValidTo,
opt =>
{
opt.MapFrom(y => y.Clients.FirstOrDefault(x => x.ValidFrom <= DateTime.Now && x.ValidTo > DateTime.Now).ValidTo);
}).
ForMember(dest => dest.FirstName,
opt =>
{
opt.MapFrom(y => y.PhysicalPeople.FirstOrDefault(x => x.ValidFrom <= DateTime.Now && x.ValidTo > DateTime.Now).FirstName);
}).
ForMember(dest => dest.LastName,
opt =>
{
opt.MapFrom(y => y.PhysicalPeople.FirstOrDefault(x => x.ValidFrom <= DateTime.Now && x.ValidTo > DateTime.Now).LastName);
}).
ForMember(dest => dest.BirthDate,
opt =>
{
opt.MapFrom(y => y.PhysicalPeople.FirstOrDefault(x => x.ValidFrom <= DateTime.Now && x.ValidTo > DateTime.Now).BirthDate);
}).
ForMember(dest => dest.FatherName,
opt =>
{
opt.MapFrom(y => y.PhysicalPeople.FirstOrDefault(x => x.ValidFrom <= DateTime.Now && x.ValidTo > DateTime.Now).FatherName);
}).
ForMember(dest => dest.CompanyName,
opt =>
{
opt.MapFrom(y => y.Companies.FirstOrDefault(x => x.ValidFrom <= DateTime.Now && x.ValidTo > DateTime.Now).CompanyName);
})
.
ForMember(dest => dest.PinNumber,
opt =>
{
opt.MapFrom(y => y.PhysicalPeople.FirstOrDefault(x => x.ValidFrom <= DateTime.Now && x.ValidTo > DateTime.Now).Pin);
}).
ForMember(dest => dest.Position,
opt =>
{
opt.MapFrom(y => y.PhysicalPeople.FirstOrDefault(x => x.ValidFrom <= DateTime.Now && x.ValidTo > DateTime.Now).Position);
}).
ForMember(dest => dest.PositionCustom,
opt =>
{
opt.MapFrom(y => y.PhysicalPeople.FirstOrDefault(x => x.ValidFrom <= DateTime.Now && x.ValidTo > DateTime.Now).PositionCustom);
}).
ForMember(dest => dest.ClientType,
opt =>
{
opt.MapFrom(y => y.Clients.FirstOrDefault(x => x.ValidFrom <= DateTime.Now && x.ValidTo > DateTime.Now).ClientType);
})
.
ForMember(dest => dest.Documents,
opt =>
{
opt.MapFrom(y => y.Documents.Where(x => x.ValidFrom <= DateTime.Now && x.ValidTo > DateTime.Now));
//opt.ExplicitExpansion();
})
.ForMember(dest => dest.ContactsInfo,
opt =>
{
opt.MapFrom(y => y.ClientContactInfoComps.Where(x => x.ValidFrom <= DateTime.Now && x.ValidTo > DateTime.Now).Select(x => x.ContactInfo));
//opt.ExplicitExpansion();
}).
ForMember(dest => dest.ClientComment,
opt =>
{
opt.MapFrom(y => y.CommentComps.Where(x => x.Contact == null).Select(x => x.Comment));
//opt.ExplicitExpansion();
}).
ForMember(dest => dest.Relations,
opt =>
{
opt.MapFrom(y => y.ClientRelationCompClient1Navigations);
//opt.ExplicitExpansion();
})
;
CreateMap<Document, DocumentContract>();
CreateMap<ContactInfo, ContactInfoContract>().
ForMember(dest => dest.ContactComments,
opt =>
{
opt.MapFrom(y => y.CommentComps.Select(x => x.Comment));
});
CreateMap<ClientRelationComp, RelationContract>().
ForMember(dest => dest.ClientINN,
opt => {
opt.MapFrom(x => x.Client2);
}).
ForMember(dest => dest.RelationType,
opt => {
opt.MapFrom(x => x.RelationId);
});
CreateMap<ICollection<Client>, ClientContract>();
CreateMap<ICollection<PhysicalPerson>, ClientContract>();
CreateMap<ICollection<Company>, ClientContract>();
CreateMap<Comment, CommentContract>();
CreateMap<ICollection<Comment>, ICollection<ContactInfoContract>>();
CreateMap<ICollection<ClientRelationComp>, ClientRef>();
}
}
我的控制器:
public class ClientContractController : ODataController
{
CRMContext _context;
IMapper _mapper;
public ClientContractController(CRMContext ctx, IMapper mapper )
{
_context = ctx;
_mapper = mapper;
}
[EnableQuery(MaxExpansionDepth = 10)]
public IQueryable<ClientContract> Get()
{
return _mapper.ProjectTo<ClientContract>(_context.ClientRefs).Where(x => x.ValidFrom <= DateTime.Now && x.ValidTo >= DateTime.Now);
}
}
这给出了以下异常 https://localhost:44371/odata/clientcontract?$ expand = relations
this gives the following exception https://localhost:44371/odata/clientcontract?$expand=relations
System.InvalidOperationException:无法转换LINQ表达式'$ it'.以一种可以翻译的形式重写查询,或者通过插入对AsEnumerable(),AsAsyncEnumerable(),ToList()或ToListAsync()的调用来显式切换到客户端评估.请参阅 https://go.microsoft.com/fwlink/?linkid=2101038 欲获得更多信息.
在Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(表达式表达式)
在Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberAssignment(MemberAssignment memberAssignment)
在System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding节点)
在Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberInit(MemberInitExpression memberInitExpression)
在System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor访问者)
在System.Linq.Expressions.ExpressionVisitor.Visit(Expression节点)
在Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(表达式表达式)
在System.Linq.Expressions.ExpressionVisitor.VisitLambda [T](Expression 1 node) at System.Linq.Expressions.Expression
1.Accept(ExpressionVisitor访问者)处
在System.Linq.Expressions.ExpressionVisitor.Visit(Expression节点)
在Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(表达式表达式)
在System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor访问者,IArgumentProvider节点)
在System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression节点)
在System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor访问者)
在System.Linq.Expressions.ExpressionVisitor.Visit(Expression节点)
在Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(表达式表达式)
在Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberAssignment(MemberAssignment memberAssignment)
在System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding节点)
在Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberInit(MemberInitExpression memberInitExpression)
在System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor访问者)
在System.Linq.Expressions.ExpressionVisitor.Visit(Expression节点)
在Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(表达式表达式)
在Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberAssignment(MemberAssignment memberAssignment)
在System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding节点)
在Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberInit(MemberInitExpression memberInitExpression)
在System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor访问者)
在System.Linq.Expressions.ExpressionVisitor.Visit(Expression节点)
在Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(表达式表达式)
在Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Translate(SelectExpression selectExpression,表达式表达式)
在Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateSelect(ShapedQueryExpression源,LambdaExpression选择器)
在Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
在System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor访问者)
在System.Linq.Expressions.ExpressionVisitor.Visit(Expression节点)
在Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor [TResult](表达式查询)
在Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery [TResult](表达式查询,布尔异步)
在Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore [TResult](IDatabase数据库,表达式查询,IModel模型,布尔异步)
在Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<> c__DisplayClass12_0 1.<ExecuteAsync>b__0() at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func
1编译器)
在Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync [TResult](表达式查询,CancellationToken cancelledToken)
在Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync [TResult](表达式,CancellationToken cancelToken)
在Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable 1.GetAsyncEnumerator(CancellationToken cancellationToken) at Microsoft.AspNetCore.Mvc.Infrastructure.AsyncEnumerableReader.ReadInternal[T](Object value) at Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor.ExecuteAsyncEnumerable(ActionContext context, ObjectResult result, Object asyncEnumerable, Func
2阅读器上)
在Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged | 21_0(ResourceInvoker调用程序,IActionResult结果)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited | 29_0 [TFilter,TFilterAsync](ResourceInvoker调用程序,任务lastTask,状态下一个,作用域范围,对象状态,布尔值isCompleted)
在Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed上下文)
在Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext [TFilter,TFilterAsync](状态和下一个,范围和范围,对象和状态,布尔值和isCompleted)处
在Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
---从上一个引发异常的位置开始的堆栈结束跟踪---
在Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited | 19_0(ResourceInvoker调用程序,Task lastTask,Next状态,Scope作用域,对象状态,布尔值isCompleted)
在Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged | 17_1(ResourceInvoker调用程序)处
在Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask | 6_0(端点端点,任务requestTask,ILogger记录器)上
在Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext上下文)
在Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext上下文)
System.InvalidOperationException: The LINQ expression '$it' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberAssignment(MemberAssignment memberAssignment)
at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberInit(MemberInitExpression memberInitExpression)
at System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at System.Linq.Expressions.ExpressionVisitor.VisitLambda[T](Expression1 node) at System.Linq.Expressions.Expression
1.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberAssignment(MemberAssignment memberAssignment)
at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberInit(MemberInitExpression memberInitExpression)
at System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberAssignment(MemberAssignment memberAssignment)
at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberInit(MemberInitExpression memberInitExpression)
at System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Translate(SelectExpression selectExpression, Expression expression)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateSelect(ShapedQueryExpression source, LambdaExpression selector)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass12_01.<ExecuteAsync>b__0() at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func
1 compiler)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1.GetAsyncEnumerator(CancellationToken cancellationToken) at Microsoft.AspNetCore.Mvc.Infrastructure.AsyncEnumerableReader.ReadInternal[T](Object value) at Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor.ExecuteAsyncEnumerable(ActionContext context, ObjectResult result, Object asyncEnumerable, Func
2 reader)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|21_0(ResourceInvoker invoker, IActionResult result)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|29_0[TFilter,TFilterAsync](ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResultExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext[TFilter,TFilterAsync](State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
推荐答案
更新21/08/20202
没有明确说明,AutoMapper
将扩展结果中的所有成员.
Without explicit instructions, AutoMapper
will expand all members in the result.
要控制在投影过程中扩展哪些成员,请在配置中设置ExplicitExpansion
,然后传入要显式扩展的成员:
To control which members are expanded during projection, set ExplicitExpansion
in the configuration and then pass in the members you want to explicitly expand:
dbContext.Orders.ProjectTo<OrderDto>(configuration,
dest => dest.Customer,
dest => dest.LineItems);
// or string-based
dbContext.Orders.ProjectTo<OrderDto>(configuration,
null,
"Customer",
"LineItems");
// for collections
dbContext.Orders.ProjectTo<OrderDto>(configuration,
null,
dest => dest.LineItems.Select(item => item.Product));
使用OData
时使用属性名称,而不使用属性名称.
Use the property name and not the attribute Name when use OData
.
OData
客户端库依靠其自己的属性OriginalNameAttribute
来获取有关服务器发出的类/成员名称的知识.您可以在此处看到的详细信息.
OData
client library relies on it's own attribute OriginalNameAttribute
to gain knowledge about class/member names as server emits them. The details you can see from here.
这篇关于ExplicitExpansion()导致OData扩展无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!