You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Automapper类型映射异常求助:List<Order>转List<OrderDto>报错

AutoMapper映射空引用错误排查

错误信息

AutoMapper.AutoMapperMappingException: 映射类型出错。
映射类型:
List1 -> List1
System.Collections.Generic.List1[[Ordering.Domain.Aggregates.OrderAggregate.Order, Ordering.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] -> System.Collections.Generic.List1[[Ordering.Application.Queries.GetOrders.OrderDto, Ordering.Application, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]
---> AutoMapper.AutoMapperMappingException: 映射类型出错。
映射类型:
Order -> OrderDto
Ordering.Domain.Aggregates.OrderAggregate.Order -> Ordering.Application.Queries.GetOrders.OrderDto
类型映射配置:
Order -> OrderDto
Ordering.Domain.Aggregates.OrderAggregate.Order -> Ordering.Application.Queries.GetOrders.OrderDto
目标成员:
OrderItems
---> System.NullReferenceException: 对象引用未设置到对象的实例。
在 lambda_method248(Closure , Object , List1 , ResolutionContext ) --- 内部异常堆栈跟踪的结尾 --- 在 lambda_method248(Closure , Object , List1 , ResolutionContext )
--- 内部异常堆栈跟踪的结尾 ---
在 lambda_method248(Closure , Object , List1 , ResolutionContext ) 在 Ordering.Application.Queries.GetOrders.GetOrdersQueryHandler.Handle(GetOrdersQuery request, CancellationToken cancellationToken) 位置 C:\Users\porterc\Documents\Personal Projects\LostChapters\Services\Ordering\Ordering.Application\Queries\GetOrders\GetOrdersQuery.cs:第35行 在 Ordering.Application.Common.Behaviours.TransactionBehaviour2.<>c__DisplayClass4_0.<b__0>d.MoveNext() 位置 C:\Users\porterc\Documents\Personal Projects\LostChapters\Services\Ordering\Ordering.Application\Common\Behaviours\TransactionBehaviour.cs:第50行
--- 来自之前位置的堆栈跟踪结尾 ---
在 Microsoft.EntityFrameworkCore.ExecutionStrategyExtensions.<>c.<b__3_0>d.MoveNext()
--- 来自之前位置的堆栈跟踪结尾 ---
在 Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func4 operation, Func4 verifySucceeded, CancellationToken cancellationToken)
在 Ordering.Application.Common.Behaviours.TransactionBehaviour2.Handle(TRequest request, RequestHandlerDelegate1 next, CancellationToken cancellationToken) 位置 C:\Users\porterc\Documents\Personal Projects\LostChapters\Services\Ordering\Ordering.Application\Common\Behaviours\TransactionBehaviour.cs:第41行

相关代码

GetOrdersQueryHandler

public GetOrdersQueryHandler(IOrderRepository orderRepository, IMapper mapper)
{
    _orderRepository = orderRepository;
    _mapper = mapper;
}

public async Task<IEnumerable<OrderDto>> Handle(GetOrdersQuery request, CancellationToken cancellationToken)
{
    var orders = await _orderRepository.GetOrders();
    var orderDtos = _mapper.Map<List<OrderDto>>(orders);

    return orderDtos;
}

GetOrders方法

public async Task<IEnumerable<Order>> GetOrders()
{
    return await _orderingDbContext.Orders.Include(oi => oi.OrderItems).OrderBy(o => o.OrderPlaced).ToListAsync();
}

Order类

public class Order : BaseEntity, IAggregateRoot
{
    
    public int OrderTotal { get; private set; }
    public DateTime OrderPlaced { get; private set; }
    public bool OrderPaid { get; private set; }
    public bool IsCancelled { get; private set; }
    public string Message { get; private set; }
    public DeliveryAddress DeliveryAddress { get; private set; }
    public OrderStatusEnum OrderStatus { get; private set; }
    public int? PaymentMethodId { get; private set; }
    public int? CustomerId { get; private set; }

    private readonly List<OrderItem> _orderItems;
    public IReadOnlyCollection<OrderItem> OrderItems => _orderItems;
    protected Order()
    {
        _orderItems = new List<OrderItem>();
        IsCancelled = false;
    }

    public Order(string userId, string userName, DeliveryAddress deliveryAddress, CardTypeEnum cardType, string cardNumber, string cardSecurityNumber,
       string cardHolderName, DateTime cardExpiration, int? customerId = null, int? paymentMethodId = null) : this()
    {
        DeliveryAddress = deliveryAddress;
        OrderStatus = OrderStatusEnum.Pending;
        OrderPlaced = DateTime.UtcNow;
        Message = "New Order Created";
        CustomerId = customerId;
        PaymentMethodId = paymentMethodId;
        AddOrderCreatedDomainEvent(userId, userName, cardType, cardNumber,
                                cardSecurityNumber, cardHolderName, cardExpiration);
    }
}

OrderDto

public record OrderDto : IMapFrom<Order>
{
    public int Id { get; set; }
    public string Street { get; private set; }

    public string City { get; private set; }

    public string Country { get; private set; }

    public string PostCode { get; private set; }
    public OrderStatus OrderStatus { get; set; }

    private readonly List<OrderBookItemsDto> _orderItems;
    public List<OrderBookItemsDto> OrderItems => _orderItems;

    public void Mapping(Profile profile)
    {
        profile.CreateMap<Order, OrderDto>()
            .ForMember(dto => dto.Street, opt => opt.MapFrom(p => p.DeliveryAddress.Street))
            .ForMember(dto => dto.City, opt => opt.MapFrom(p => p.DeliveryAddress.City))
            .ForMember(dto => dto.Country, opt => opt.MapFrom(p => p.DeliveryAddress.Country))
            .ForMember(dto => dto.PostCode, opt => opt.MapFrom(p => p.DeliveryAddress.PostCode))
            .ForMember(dto => dto.OrderItems, opt => opt.MapFrom(p => p.OrderItems.ToList()));   
    }
}

OrderBookItemsDto

public record OrderBookItemsDto: IMapFrom<OrderItem>
{
    public int BookCatalogueId { get; private set; }
    public decimal BookPrice { get; private set; }
    public string BookTitle { get; private set; }
    public string Message { get; private set; }
    public int Quantity { get; private set; }
    public void Mapping(Profile profile)
    {
        profile.CreateMap<OrderItem, OrderBookItemsDto>(); ;
    }
}

问题分析与解决方案

核心问题

  1. OrderDto的_orderItems未初始化且为只读:_orderItems是私有只读字段,未在构造函数中初始化,AutoMapper映射时无法为其赋值,导致空引用异常。
  2. 部分属性为private set:Street、City等属性设置为私有写入,AutoMapper默认无法对这类属性赋值。

解决方案

修改OrderDto,调整字段的可访问性并初始化集合:

public record OrderDto : IMapFrom<Order>
{
    public int Id { get; set; }
    public string Street { get; set; }
    public string City { get; set; }
    public string Country { get; set; }
    public string PostCode { get; set; }
    public OrderStatus OrderStatus { get; set; }

    public List<OrderBookItemsDto> OrderItems { get; set; } = new List<OrderBookItemsDto>();

    public void Mapping(Profile profile)
    {
        profile.CreateMap<Order, OrderDto>()
            .ForMember(dto => dto.Street, opt => opt.MapFrom(p => p.DeliveryAddress.Street))
            .ForMember(dto => dto.City, opt => opt.MapFrom(p => p.DeliveryAddress.City))
            .ForMember(dto => dto.Country, opt => opt.MapFrom(p => p.DeliveryAddress.Country))
            .ForMember(dto => dto.PostCode, opt => opt.MapFrom(p => p.DeliveryAddress.PostCode))
            .ForMember(dto => dto.OrderItems, opt => opt.MapFrom(p => p.OrderItems));
    }
}

额外说明

  • 源Order的OrderItems是IReadOnlyCollection<OrderItem>,AutoMapper可直接映射为List<OrderBookItemsDto>,无需额外调用ToList()。
  • 确保OrderItem与OrderBookItemsDto的字段名称匹配,若字段名不一致需手动配置映射关系。

内容的提问来源于stack exchange,提问作者Ports

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 06:54:57