ExplicitExpansion () menyebabkan OData meluas tidak berfungsi

Aug 20 2020

Saat menggunakan ExplicitExpansion (), Odata memperluas tidak berfungsi. Model DTo dan EF saya dapat ditemukan di tautan di bawah ini. Membuat kueri DTO berdasarkan EF menggunakan Odata

Kelas Automapper saya:

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>();
        
    }
}

Pengontrol Saya:

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);
    }
}

ini memberikan pengecualian berikut https: // localhost: 44371 / odata / clientcontract? $ expand = relations

System.InvalidOperationException: Ekspresi LINQ '$ it' tidak dapat diterjemahkan. Tulis ulang kueri dalam bentuk yang bisa diterjemahkan, atau beralih ke evaluasi klien secara eksplisit dengan memasukkan panggilan ke AsEnumerable (), AsAsyncEnumerable (), ToList (), atau ToListAsync (). Lihathttps://go.microsoft.com/fwlink/?linkid=2101038untuk informasi lebih lanjut. di Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit (Ekspresi ekspresi) di Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberAssignment (MemberAssignment memberAssignmentFindingions.Linionq.ExpressBindingions node.Linionq.ExpressBindingions) di System.Linionq.ExpressBindingions.Linionq.Express .Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberInit (MemberInitExpression memberInitExpression) di System.Linq.Expressions.MemberInitExpression.Accept (pengunjung ExpressionVisitor) di System.Linq.Expressions.ExpressionVisitor.VationalProject.Expressionework di Microsoft.EternalntityFramisitexpression node. .Kunjungi (ekspresi ekspresi) di System.Linq.Expressions.ExpressionVisitor.VisitLambda [T] (Ekspresi1 node) at System.Linq.Expressions.Expression1. Terima (Pengunjung ExpressionVisitor) di System.Linq.Expressions.ExpressionVisitor.Visit (node ​​ekspresi) di Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit (ekspresi ekspresi) di System.Dynamic.Utils.ExpressionVisitorUtils.VisitionArguments , Node IArgumentProvider) di System.Linq.Expressions.ExpressionVisitor.VisitMethodCall (node ​​MethodCallExpression) di System.Linq.Expressions.MethodCallExpression.Accept (pengunjung ExpressionVisitor) di System.Linq.Expressions.ExpressionVisitor.Visit (node ​​ExpressionFrameworkCoreity) di Microsoft.Ent .Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit (Ekspresi ekspresi) di Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberAssignment (MemberAssignment memberAssignment) di System.Linq.Expressions.ExpressionVemberntityQuery.VisitMemberAssignment .RelationalProjecti onBindingExpressionVisitor.VisitMemberInit (MemberInitExpression memberInitExpression) di System.Linq.Expressions.MemberInitExpression.Accept (pengunjung ExpressionVisitor) di System.Linq.Expressions.ExpressionVisitor.Visit (node ​​Ekspresi) di Microsoft.EntityFrameworkCore.Query.Internal.RelExpress ) di Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitMemberAssignment (MemberAssignment memberAssignment) di System.Linq.Expressions.ExpressionVisitor.VisitMemberBinding (node ​​MemberBinding) di Microsoft.EntityFrameworkCore.QueryInExpressionExpressBinding System.Linq.Expressions. Linq.Expressions.MemberInitExpression.Accept (pengunjung ExpressionVisitor) di System.Linq.Expressions.ExpressionVisitor.Visit (node ​​ekspresi) di Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Visit (Express ekspresi ion) di Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Translate (SelectExpression selectExpression, ekspresi Expression) di Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisExpressionVisitor.Translate (SelectExpression selectExpression, ekspresi Expression) di Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisExpressionVisitor.Translate (sumber ShapedQueryransExpression.Query.expressionEntexpressions.Query. MethodCallExpression methodCallExpression) di System.Linq.Expressions.MethodCallExpression.Accept (pengunjung ExpressionVisitor) di System.Linq.Expressions.ExpressionVisitor.Visit (node ​​ekspresi) di Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor [TResult] di Microsoft Expression query .EntityFrameworkCore.Storage.Database.CompileQuery [TResult] (Permintaan ekspresi, Boolean async) di Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore [TResult] (database IDatabase, kueri Ekspresi, model IModel, Boolean as ync) di Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler. <> c__DisplayClass12_0 1.<ExecuteAsync>b__0() at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func1 kompiler) di Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync [TResult] (Permintaan ekspresi, CancellationToken cancellationTokenToken.Query.Internal) di Microsoft.Ent. EntityQueryProvider.ExecuteAsync [TResult] (Ekspresi ekspresi, CancellationToken cancellationToken) di Microsoft.EntityFrameworkCore.Query.Internal.EntityQuerable 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, Func2 reader) di Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged | 21_0 (hasil) di Microsoft.Invoker, IAResoker, IA AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited | 29_0 [TFilter, TFilterAsync] (resourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) di Microsoft.AspNetCore.Mealvc.Infrastructure.ResourceInvoker.Rethrow (ResultExecuted contextContextControw ) di Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.ResultNext [TFilter, TFilterAsync] (Status & berikutnya, Cakupan & sc ope, Object & state, Boolean & isCompleted) di Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeResultFilters () --- Akhir dari pelacakan tumpukan dari lokasi sebelumnya tempat pengecualian dilemparkan --- di Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker. g__Awaited | 19_0 (ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) di Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Logged | 17_1 (ResourceInvoker invoker) di Microsoft.AspNetCore.Routing.EndpointMiddleware.g__ | 6_0 (Endpoint endpoint, Task requestTask, ILogger logger) di Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke (konteks HttpContext) di Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke (konteks HttpContext)

Jawaban

MichaelWang Aug 20 2020 at 15:46

Perbarui 21/08/20202

Tanpa instruksi eksplisit , AutoMapperakan memperluas semua anggota dalam hasil.

Untuk mengontrol anggota mana yang diperluas selama proyeksi, setel ExplicitExpansiondalam konfigurasi dan kemudian teruskan anggota yang ingin Anda luaskan secara eksplisit:

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));



Gunakan nama properti dan bukan Nama atribut saat digunakan OData.

ODataperpustakaan klien bergantung pada atributnya sendiri OriginalNameAttributeuntuk mendapatkan pengetahuan tentang nama kelas / anggota saat server memancarkannya. Detailnya bisa Anda lihat dari sini .