如何将参数传递给 AutoMapper 配置文件?

问题描述 投票:0回答:1

对于父表中的每一行,子表中都有许多子行。但是子行对于具有“JointId”和“NdtId”的每个父行都是唯一的,当我从存储库调用“GetLineJointsForNdtSelectionAsync”时,我希望使用“JointId”和“NdtId”过滤数据。 “JointId”可在解析器中访问,“NdtId”必须从存储库中的“GetLineJointsForNdtSelectionAsync”传递:

.ProjectTo<Models.Output.Piping.LineJoints.LineJointForNdtSelection>(
            _mapper.ConfigurationProvider,
            new { ndtId = query.NdtId })

但是从“GetLineJointsForNdtSelectionAsync”传递到解析器类的值是空 GUID。然后我使用“(Guid)context.Items[“ndtId”]”来获取配置文件类中传递的值,但出现以下异常:

无法从创建地图表达式。 (Ces.Caspian.Domain.Entities.Piping.LineJoints.LineJoint) 到 String.NdtType (System.String) 映射类型:LineJoint -> LineJointForNdtSelection Ces.Caspian.Domain.Entities.Piping.LineJoints.LineJoint -> Ces.Caspian。 Models.Output.Piping.LineJoints.LineJointForNdtSelection 类型映射配置:LineJoint -> LineJointForNdtSelection Ces.Caspian.Domain.Entities.Piping.LineJoints.LineJoint -> Ces.Caspian.Models.Output.Piping.LineJoints.LineJointForNdtSelection 目标成员:NdtType。

父表:

public class LineJoint : EntityBase
{
    public const int JointNoIndexMaxLength = 5;
    public const int JointNoMaxLength = 20;

    public LineJoint()
    {
    }

    public LineJoint(Guid? userId) : base(userId)
    {
    }

    public Guid? ContractorId { get; set; }
    public Guid? LineSheetId { get; set; }
    public string? JointNo { get; set; }
    public Guid? ScheduleId { get; set; }
    public Guid? ConnectionTypeId { get; set; }
    public Guid? EndStatusId { get; set; }
    public Guid? EndTypeId { get; set; }
    public Guid? JointTypeId { get; set; }
    public Guid? LocationId { get; set; }
    public Guid? WeldTypeId { get; set; }
    public int Revision { get; set; }
    public Guid? TestPackageId { get; set; }

    // Navigation

    public Domain.Entities.Project.Contractors.Contractor? Contractor { get; set; }
    public Domain.Entities.Piping.LineSheets.LineSheet? LineSheet { get; set; }
    public Domain.Entities.Piping.ConnectionTypes.ConnectionType? ConnectionType { get; set; }
    public Domain.Entities.Piping.EndTypes.EndType? EndType { get; set; }
    public Domain.Entities.Piping.EndStatuses.EndStatus? EndStatus { get; set; }
    public Domain.Entities.Piping.JointTypes.JointType? JointType { get; set; }
    public Domain.Entities.Piping.Locations.Location? Location { get; set; }
    public Domain.Entities.Piping.WeldTypes.WeldType? WeldType { get; set; }
    public Domain.Entities.TestPackage.TestPackages.TestPackage? TestPackage { get; set; }
    public Domain.Entities.Piping.Schedules.Schedule? Schedule { get; set; }
    public List<Domain.Entities.Piping.NdtStatuses.NdtStatus>? NdtStatuses { get; set; }
}

儿童桌:

public class NdtStatus : Entities.EntityBase
{
    public const int NDTNoMaxLength = 50;

    public NdtStatus()
    {
    }

    public NdtStatus(Guid? userId) : base(userId)
    {
    }

    public Guid? LineJointId { get; set; }
    public Guid? NdtId { get; set; }
    public bool Required { get; set; }
    public bool Exempted { get; set; }
    public string? NdtNo { get; set; }
    public Guid? NdtTypeId { get; set; }

    // Navigation

    public Domain.Entities.Piping.LineJoints.LineJoint? LineJoint { get; set; }
    public Domain.Entities.Piping.Ndts.Ndt? Ndt { get; set; }
    public Domain.Entities.Piping.NdtTypes.NdtType? NdtType { get; set; }
}

输出型号:

public class LineJointForNdtSelection : OutputModelEssentials
{
    // From parent table

    public Guid JointId { get; set; }
    public string? Contractor { get; set; }
    public string? SheetNo { get; set; }
    public string? JointNo { get; set; }
    public string? ConnectionType { get; set; } 
    public string? EndStatus { get; set; } 
    public string? EndType { get; set; }
    public string? JointType { get; set; } 
    public string? Location { get; set; } 
    public string? PackageNo { get; set; }

    // From child table

    public string? Ndt { get; set; }
    public string? NdtType { get; set; }
    public bool Required { get; set; }
    public bool Exempted { get; set; }
    public string? NdtNo { get; set; }
    public string? RequestNo { get; set; }
    public string? ReportNo { get; set; }
    public string? Result { get; set; }
}

用于映射的 AutoMapper 配置文件类:

public class LineJointForNdtSelection : AutoMapper.Profile
{
    public LineJointForNdtSelection()
    {
        CreateMap<
            Domain.Entities.Piping.LineJoints.LineJoint,
            Models.Output.Piping.LineJoints.LineJointForNdtSelection>()

        // From parent table

            .ForMember(x => x.JointId, x => x.MapFrom(x => x.Id))
            .ForMember(x => x.Contractor, x => x.MapFrom(x => x.Contractor.Name))
            .ForMember(x => x.SheetNo, x => x.MapFrom(x => x.LineSheet.SheetNo))
            .ForMember(x => x.ConnectionType, x => x.MapFrom(x => x.ConnectionType.Name))
            .ForMember(x => x.EndStatus, x => x.MapFrom(x => x.EndStatus.Name))
            .ForMember(x => x.EndType, x => x.MapFrom(x => x.EndType.Name))
            .ForMember(x => x.JointType, x => x.MapFrom(x => x.JointType.Name))
            .ForMember(x => x.Location, x => x.MapFrom(x => x.Location.Name))
            .ForMember(x => x.PackageNo, x => x.MapFrom(x => x.TestPackage.TestPackageNo))

        // From child table

            .ForMember(x => x.NdtType, opt => opt.MapFrom((src, dest, destMember, context)
                => new Profiles.Piping.NdtStatuses.Resolvers.NdtTypeResolver((Guid)context.Items["ndtId"])
                    .Resolve(src, dest, destMember, context)));
        ;
    }
}

客户解析器:

public class NdtTypeResolver : IValueResolver<
    Ces.Caspian.Domain.Entities.Piping.LineJoints.LineJoint,
    Ces.Caspian.Models.Output.Piping.LineJoints.LineJointForNdtSelection,
    string?>
{
    private Guid? _ndtId;

    public NdtTypeResolver()
    {

    }

    public NdtTypeResolver(Guid? ndtId = null)
    {
        _ndtId = ndtId;
    }

    public string? Resolve(
        Ces.Caspian.Domain.Entities.Piping.LineJoints.LineJoint source,
        Ces.Caspian.Models.Output.Piping.LineJoints.LineJointForNdtSelection destination,
        string? destMember,
        ResolutionContext context)
    {
        return source.NdtStatuses?.FirstOrDefault(c
            => c.LineJointId == source.Id && c.NdtId == _ndtId)?.NdtType?.Name ?? string.Empty;
    }
}

存储库方法:

public async Task<List<Models.Output.Piping.LineJoints.LineJointForNdtSelection>> GetLineJointsForNdtSelectionAsync(
    Models.Input.Queries.Piping.LineJoints.GetLineJointsForNdtSelection query)
{
    var result = await _dbContext.LineJoints
        .Where(x => x.LineSheet.LineNumberId == query.LineNumberId)
        .ProjectTo<Models.Output.Piping.LineJoints.LineJointForNdtSelection>(
            _mapper.ConfigurationProvider,
            new { ndtId = query.NdtId })
        .AsNoTracking()
        .ToListAsync()
        ;

    return result;
}

我已将解析器注册到服务,但没有解决问题。有一个简单的解决方案,但我认为这不是最好的解决方案,但有效。在我的上一个解决方案中,我必须为每个“NdtId”创建多配置文件类,然后在我的存储库中检查哪个“Id”传递给方法,然后调用内部方法来获取所需的数据,然后返回给用户。

c# .net automapper
1个回答
0
投票

我的问题已经解决了。当我使用 ProjectTo 将数据从数据库映射到类时,_mapper.ConfigurationProvider 之后的第二个参数无法为 ResolutionContext 赋值。最终的解决方案是,首先从数据库映射数据,然后,为了将数据映射到输出模型,我们可以为ResolutionContext赋值,以将值传递给解析器。事实上,我只是重构了我的存储库方法:

        public async Task<List<Models.Output.Piping.LineJoints.LineJointForNdtSelection>> GetLineJointsForNdtSelectionAsync(
        Models.Input.Queries.Piping.LineJoints.GetLineJointsForNdtSelection query)
    {
        var initialResult = await _dbContext.LineJoints
            .Where(x => x.LineSheet.LineNumberId == query.LineNumberId)
            .Select(s => new Models.Output.Piping.LineJoints.LineJointForNdtSelection
            {
                JointId = s.Id,
                Contractor = s.Contractor == null ? null : s.Contractor.Name,
                SheetNo = s.LineSheet == null ? null : s.LineSheet.SheetNo.ToString(),
                JointNo = s.JointNo == null ? null : s.JointNo,
                ConnectionType = s.ConnectionType == null ? null : s.ConnectionType.Name,
                EndStatus = s.EndStatus == null ? null : s.EndStatus.Name,
                EndType = s.EndType == null ? null : s.EndType.Name,
                JointType = s.JointType == null ? null : s.JointType.Name,
                Location = s.Location == null ? null : s.Location.Name,
                PackageNo = s.TestPackage == null ? null : s.TestPackage.TestPackageNo,

                // NDT Status


                Ndt = s.NdtStatuses == null ? null :
                    s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId) == null ? null :
                    s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId).Ndt.Name,

                NdtType = s.NdtStatuses == null ? null :
                    s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId) == null ? null :
                    s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId).NdtType.Name,

                Required = s.NdtStatuses == null ? false :
                    s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId) == null ? false :
                    s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId).Required,

                Exempted = s.NdtStatuses == null ? false :
                    s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId) == null ? false :
                    s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId).Exempted,

                NdtNo = s.NdtStatuses == null ? null :
                    s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId) == null ? null :
                    s.NdtStatuses.FirstOrDefault(x => x.LineJointId == s.Id && x.NdtId == query.NdtId).NdtNo,

                RequestNo = string.Empty,
                ReportNo = string.Empty,
                Result = string.Empty,
            })
            .AsNoTracking()
            .ToListAsync()
            ;

        var data = _mapper.Map<List<Models.Output.Piping.LineJoints.LineJointForNdtSelection>>(initialResult, option =>
        {
            option.Items["ndtId"] = query.NdtId;
        });

        return data;
    }

通过自定义解析器映射所需的属性(现在我可以使用 context.Items["ndtId"]):

.ForMember(x => x.Required, opt => opt.MapFrom((src, dest, destMember, context)
=> new Profiles.Piping.NdtStatuses.Resolvers.ExemptedResolver((Guid?)context.Items["ndtId"])
.Resolve(src, dest, destMember, context)))
© www.soinside.com 2019 - 2024. All rights reserved.