ExplicitExpansion()により、OData展開が機能しなくなります

Aug 20 2020

ExplicitExpansion()を使用する場合、Odata展開は機能しません。私のDToモデルとEFモデルはリンクの下にあります。Odataを使用したEFに基づくDTOのクエリ

私のオートマッパークラス:

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

System.InvalidOperationException:LINQ式 '$ it'を変換できませんでした。翻訳可能な形式でクエリを書き直すか、AsEnumerable()、AsAsyncEnumerable()、ToList()、またはToListAsync()のいずれかに呼び出しを挿入して、クライアント評価に明示的に切り替えます。見るhttps://go.microsoft.com/fwlink/?linkid=2101038詳細については。 Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Expression expression)at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberAssignment(MemberAssignment memberAssignment)at System.Linq.Expressions.ExpressionVisitor.Visitor Microsoft.EntityFrameworkのSystem.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor visitor)at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)の.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberInit(MemberInitExpression memberInitExpression) System.Linq.Expressions.ExpressionVisitor.VisitLambda [T](Expression)での.Visit(Expression式)1 node) at System.Linq.Expressions.Expression1.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 、IArgumentProviderノード)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( .RelationalProjecti onBindingExpressionVisitor.VisitMemberInit(MemberInitExpression memberInitExpression)at System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor visitor)at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)at Microsoft.EntityFrameworkCore.Query.Internal.Relation )Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberAssignment(MemberAssignment memberAssignment)at System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding(MemberBinding node)at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBinding Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit(Express)のSystem.Linq.Expressions.ExpressionVisitor.Visit(Expressionノード)のLinq.Expressions.MemberInitExpression.Accept(ExpressionVisitorビジター)Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateSelect(ShapedQueryExpression source、LambdaExpressionselector)のMicrosoft.EntityFrameworkCore.Query.QueryableMethodのMicrosoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Translate(SelectExpression selectExpression、Expression expression) 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 as ync)atMicrosoft.EntityFrameworkCore.Query.Internal.QueryCompiler。<> c__DisplayClass12_0 1.<ExecuteAsync>b__0() at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func1コンパイラ)at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync [TResult](Expression query、CancellationToken cancelToken)atMicrosoft.EntityFrameworkCore.Query.Internal 。 MicrosoftのEntityQueryProvider.ExecuteAsync [TResult](式、CancellationToken 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, FunccancelToken)(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable 2リーダー)(Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged | 21_0(ResourceInvoker呼び出し側、IActionResultの結果))。 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 )Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext [TFilter、TFilterAsync](State&next、Scope&sc ope、Object&state、Boolean&isCompleted)at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters()---例外がスローされた前の場所からのスタックトレースの終わり--- 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__AwaitRequest | 6_0(エンドポイントエンドポイント、タスクrequestTask、ILoggerロガー)at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

回答

MichaelWang Aug 20 2020 at 15:46

更新21/08/20202

なければ、明示的な指示、AutoMapper結果内のすべてのメンバーを拡大していきます。

投影中に展開されるメンバーを制御するにExplicitExpansionは、構成を設定してから、明示的に展開するメンバーを渡します。

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

ODataクライアントライブラリはOriginalNameAttribute、サーバーがクラス/メンバー名を発行するときに、クラス/メンバー名に関する知識を得るためにそれ自体の属性に依存しています。あなたがここから見ることができる詳細。