Cześć, używam Auto Mapper, aby mapować jednostkę kondycjonalną, która nie działa bez użycia po mapie, ale działa dobrze z po mapie, której nie będę nie używać. Chcę mapować invanoelineCreditheader z Domain.permanenPlacement, ale warunkowo.

Poniżej znajduje się kod mapowania.

 MauritiusMapper.CreateMap<Domain.PermanentPlacement, InvoiceLineCreditHeader>()
                                .ForMember(desc => desc.ApplicantName, o => o.MapFrom(source => source.Candidate.FullName))
                                .ForMember(desc => desc.DatePlaced, o => o.MapFrom(source => source.PlacementDate))
                                .ForMember(desc => desc.ApproveDate, o => o.MapFrom(source => source.LastAuditItem.DateOfAction))
                                .ForMember(desc => desc.CheckedBy, o => o.MapFrom(source => source.StartCheckedBy))
                                .ForMember(desc => desc.Job, o => o.MapFrom(source => source.JobTitle));

        MauritiusMapper.CreateMap<InvoiceLineCreditSearchResult, InvoiceLineCreditData>()
            .ForMember(d => d.InvoiceLineCredits, o => o.MapFrom(s => s.Credits))
            .ForMember(d => d.InvoiceLineCreditHeader, o => o.MapFrom(s => s.InvoiceLine))
            .ForMember(d => d.CreditReasons, o => o.MapFrom(s => s.CreditReasons))
            .ForMember(d => d.CreditStatuses, o => o.MapFrom(s => s.CreditStatuses))
            .ForMember(d => d.InvoiceLineCreditHeader, o => o.MapFrom(s => s.InvoiceLine.TransactionLines.OfType<PermanentPlacementTransactionLine>().FirstOrDefault()?.PermanentPlacement ?? s.ReissuePermanentPlacement))

To daje błąd.

Lambda drzewa wyrażenia nie może zawierać operatora propagowania zerowego.

Który jest wyjaśniony przez Dlaczego nie mogę użyć Operator propagacji NULL w wyrażeniach Lambda?

Jeśli używam Aftermap, działa dobrze.

        MauritiusMapper.CreateMap<InvoiceLineCreditSearchResult, InvoiceLineCreditData>()
            .ForMember(d => d.InvoiceLineCredits, o => o.MapFrom(s => s.Credits))
            .ForMember(d => d.InvoiceLineCreditHeader, o => o.MapFrom(s => s.InvoiceLine))
            .ForMember(d => d.CreditReasons, o => o.MapFrom(s => s.CreditReasons))
            .ForMember(d => d.CreditStatuses, o => o.MapFrom(s => s.CreditStatuses))
            //.ForMember(d => d.InvoiceLineCreditHeader, o => o.MapFrom(s => s.InvoiceLine.TransactionLines.OfType<PermanentPlacementTransactionLine>().FirstOrDefault()?.PermanentPlacement ?? s.ReissuePermanentPlacement))
            .AfterMap((s, d) =>
            {
                var placement
                = s.InvoiceLine.TransactionLines.OfType<PermanentPlacementTransactionLine>().FirstOrDefault()?.PermanentPlacement ?? s.ReissuePermanentPlacement;
                //  if (placement == null) return;


                d.InvoiceLineCreditHeader.ApplicantId = placement.ApplicantId;
                d.InvoiceLineCreditHeader.ApplicantName = placement.Candidate.FullName;
                d.InvoiceLineCreditHeader.Job = placement.JobTitle;
                d.InvoiceLineCreditHeader.DatePlaced = placement.PlacementDate;
                d.InvoiceLineCreditHeader.PlacedBy = placement.PlacedBy;
                d.InvoiceLineCreditHeader.ApprovedBy = placement.ApprovedBy;
                d.InvoiceLineCreditHeader.ApproveDate = placement.LastAuditItem.DateOfAction;
                d.InvoiceLineCreditHeader.CheckedBy = placement.StartCheckedBy;
                d.InvoiceLineCreditHeader.StartDate = placement.StartDate;
            });

Czy jest jakiś sposób w auto Mapper, mogę to osiągnąć bez użycia Aftermap? Istnieje również stan, ale stosuje się również wyrażenie LINQ.

Jakieś pomysły ?

0
jjj 16 luty 2017, 11:47

2 odpowiedzi

Najlepsza odpowiedź

Musisz znaleźć alternatywę dla operatora ?.

s.InvoiceLine.TransactionLines.OfType<PermanentPlacementTransactionLine>()
    .FirstOrDefault()?.PermanentPlacement

Który jest dość prosty przez Select - ing PermanentPlacement przed FirstOrDefault:

s.InvoiceLine.TransactionLines.OfType<PermanentPlacementTransactionLine>()
    .Select(e => e.PermanentPlacement).FirstOrDefault()
3
Ivan Stoev 16 luty 2017, 09:15

Możesz utworzyć osobną metodę z żądaną logiką:

private InvoiceLineCreditHeader GetInvoiceLineCreditHeader(InvoiceLineCreditSearchResult result)
{
    // todo: get InvoiceLineCreditHeader conditionally
    InvoiceLineCreditHeader header = new InvoiceLineCreditHeader();
    return header;
}

I nazwij to tak:

.ForMember(d => d.InvoiceLineCreditHeader, o => o.MapFrom(s => GetInvoiceLineCreditHeader(s)))
1
Kenneth T. 16 luty 2017, 09:22