Mapster - Nested Navigational Property Map

230 Views Asked by At

I use mapster to map my db model and dto object mapping, but i getting some projection error.

I set mapster global config like this:

TypeAdapterConfig.GlobalSettings.Default.PreserveReference(true);

My db model and dto classes are like this:

 public class AdapterMessage : BaseEntity<Guid>, IAggregateRoot
{
    public string MessageID { get; set; }
    public string? MessageKey { get; set; }
    public string? ScenarioIdentifier { get; set; }
    public string? SenderName { get; set; }
    public string? ReceiverName { get; set; }
    public string? InterfaceName { get; set; }
    public string? Namespace { get; set; }
    public string? ErrorLabel { get; set; }
    public string? ErrorCode { get; set; }
    public DateTime? StartTime { get; set; }
    public DateTime? EndTime { get; set; }
    public DateTime? PersistUntil { get; set; }
    public DateTime? ValidUntil { get; set; }
    public string? MessageType { get; set; }
    public string? NodeId { get; set; }
    public string? QualityOfService { get; set; }
    public string? Status { get; set; }
    public string Size { get; set; }
    public bool? Cancelable { get; set; }
    public string? ConnectionName { get; set; }
    public string? Credential { get; set; }
    public string? Direction { get; set; }
    public bool? Editable { get; set; }
    public string? Endpoint { get; set; }
    public string? Headers { get; set; }
    public string? IsPersistent { get; set; }
    public string? Protocol { get; set; }
    public string? ReceiverInterfaceName { get; set; }
    public string? ReceiverInterfaceNameSpace { get; set; }
    public string? ReceiverPartyAgency { get; set; }
    public string? ReceiverPartyName { get; set; }
    public string? ReceiverPartySchema { get; set; }
    public bool? Restartable { get; set; }
    public string? Retries { get; set; }
    public string? RetryInterval { get; set; }
    public string? SenderInterfaceName { get; set; }
    public string? SenderInterfaceNameSpace { get; set; }
    public string? SenderPartyAgency { get; set; }
    public string? SenderPartyName { get; set; }
    public string? SenderPartySchema { get; set; }
    public string? SequenceNumber { get; set; }
    public string? SerializationContext { get; set; }
    public string? TimesFailed { get; set; }
    public string? Version { get; set; }
    public bool? WasEdited { get; set; }
    public string? PayloadPermissionWarning { get; set; }
    public string? Duration { get; set; }
    public string? MessagePriority { get; set; } 
    public string? MessageListBytesXmlAM { get; set; }
    public string? MessageListBytesXmlBI { get; set; }
    public string? MessageListBytesXmlMS { get; set; }
    public string? MessageListBytesXmlSC { get; set; }
    public bool? IsMessageListBytesWritter { get; set; } 
    public DateTime? LastAuditLogQueryDate { get; set; }

    public List<AdapterMessageAuditLog> AdapterMessageAuditLogs { get; set; }
}

My Dto class like this:

using Application.Sap.AdapterMessageAuditLog;
using Domain.Common.Contracts;

namespace Application.Sap.AdapterMessage
{
    public class AdapterMessageDto : BaseDto
    {
        public string MessageID { get; set; }
        public string? MessageKey { get; set; }
        public string? ScenarioIdentifier { get; set; }
        public string? SenderName { get; set; }
        public string? ReceiverName { get; set; }
        public string? InterfaceName { get; set; }
        public string? Namespace { get; set; }
        public int? ErrorLabel { get; set; }
        public string? ErrorCode { get; set; }
        public DateTime? StartTime { get; set; }
        public DateTime? EndTime { get; set; }
        public DateTime? PersistUntil { get; set; }
        public DateTime? ValidUntil { get; set; }
        public string? MessageType { get; set; }
        public int? NodeId { get; set; }
        public string? QualityOfService { get; set; }
        public string? Status { get; set; }
        public long Size { get; set; }
        public bool? Cancelable { get; set; }
        public string? ConnectionName { get; set; }
        public string? Credential { get; set; }
        public string? Direction { get; set; }
        public bool? Editable { get; set; }
        public string? Endpoint { get; set; }
        public string? Headers { get; set; }
        public bool? IsPersistent { get; set; }
        public string? Protocol { get; set; }
        public string? ReceiverInterfaceName { get; set; }
        public string? ReceiverInterfaceNameSpace { get; set; }
        public string? ReceiverPartyAgency { get; set; }
        public string? ReceiverPartyName { get; set; }
        public string? ReceiverPartySchema { get; set; }
        public bool? Restartable { get; set; }
        public int? Retries { get; set; }
        public int? RetryInterval { get; set; }
        public string? SenderInterfaceName { get; set; }
        public string? SenderInterfaceNameSpace { get; set; }
        public string? SenderPartyAgency { get; set; }
        public string? SenderPartyName { get; set; }
        public string? SenderPartySchema { get; set; }
        public int? SequenceNumber { get; set; }
        public string? SerializationContext { get; set; }
        public int? TimesFailed { get; set; }
        public int? Version { get; set; }
        public bool? WasEdited { get; set; }
        public string? PayloadPermissionWarning { get; set; }
        public long Duration { get; set; }
        public int? MessagePriority { get; set; }
        public string? MessageListBytesXmlAM { get; set; }
        public string? MessageListBytesXmlBI { get; set; }
        public string? MessageListBytesXmlMS { get; set; }
        public string? MessageListBytesXmlSC { get; set; }
        public bool? IsMessageListBytesWritter { get; set; }
        public DateTime? LastAuditLogQueryDate { get; set; }
        public List<AdapterMessageAuditLogDto> AdapterMessageAuditLogs { get; set; }
    }
}

When i comment public List<AdapterMessageAuditLogDto> AdapterMessageAuditLogs { get; set; } property, everything works fine, but if i want to map this property then getting this error:

Error while compiling\nsource=Domain.Entity.SAP.AdapterMessage\ndestination=Application.Sap.AdapterMessage.AdapterMessageDto\ntype=Projection

I use ardalis specifiaction, so i use mapster method in my repository like this:

using Application.Common.Persistence;
using Ardalis.Specification;
using Ardalis.Specification.EntityFrameworkCore;
using Domain.Common.Contracts;
using Domain.Entity.Configuration;
using Infrastructure.Persistance.Context;
using Mapster;
using Microsoft.EntityFrameworkCore.Storage;

namespace Infrastructure.Persistance.Repository
{
    // Inherited from Ardalis.Specification's RepositoryBase<T>
    public class ApplicationDbRepository<T> : RepositoryBase<T>, IReadRepository<T>, IRepository<T>
        where T : class, IAggregateRoot
    {
        private readonly ApplicationDbContext _context;
        public ApplicationDbRepository(ApplicationDbContext dbContext)
            : base(dbContext)
        {
            _context = dbContext;
        }

        // We override the default behavior when mapping to a dto.
        // We're using Mapster's ProjectToType here to immediately map the result from the database.
        // This is only done when no Selector is defined, so regular specifications with a selector also still work.
        protected override IQueryable<TResult> ApplySpecification<TResult>(ISpecification<T, TResult> specification) =>
            specification.Selector is not null
                ? base.ApplySpecification(specification)
                : ApplySpecification(specification, false)
                    .ProjectToType<TResult>();


        public IDbContextTransaction BeginTransaction() => _context.Database.BeginTransaction();

    }
}
1

There are 1 best solutions below

0
On

I resolved the problem. You see, entities are recursively referencing each other so Mapster tries to map every object. To stop that, you must set the max depth value.

TypeAdapterConfig<AdapterMessage, AdapterMessageDto>.NewConfig().MaxDepth(2);

For more: Mapster Object Reference