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

.NET Core Get API报错:无法将匿名类型转换为PurchaseOrderHeaderDto

问题分析与修复

问题根源

你遇到的InvalidCastException是因为类型不匹配:
在Handle方法的LINQ查询中,你创建了一组匿名类型的对象,但方法需要返回IEnumerable<PurchaseOrderHeaderDto>类型。.NET无法自动将匿名类型转换为自定义的Dto类,因此抛出转换异常。

具体来看这段代码:

var result = (from poList in data
              join vList in vendorList on poList.VendorId equals vList.Id
              select new
              {
                  poList.Id,
                  poList.Date,
                  poList.VendorId,
                  vList.Name
              }).ToList();

这里select new {...}生成的是.NET自动创建的匿名类型,而非你定义的PurchaseOrderHeaderDto,但后续你试图将这个匿名列表传入期待PurchaseOrderHeaderDto集合的ResultModel.Create()方法,导致类型转换失败。

修复方案

方案1:直接在LINQ中实例化PurchaseOrderHeaderDto

修改LINQ查询,直接创建PurchaseOrderHeaderDto的实例,确保赋值的属性与Dto类的属性名称一致(请根据你的PurchaseOrderHeaderDto实际结构调整属性名):

public async Task<ResultModel<IEnumerable<PurchaseOrderHeaderDto>>> Handle(GetPurchaseOrderListQuery request, CancellationToken cancellationToken)
{
    var data = await _purchaseOrderHeaderRepository.GetAllAsync();
    var vendorList = await _vendorRepository.GetAllAsync();

    // 直接实例化目标Dto类
    var result = (from poList in data
                  join vList in vendorList on poList.VendorId equals vList.Id
                  select new PurchaseOrderHeaderDto
                  {
                      Id = poList.Id,
                      Date = poList.Date,
                      VendorId = poList.VendorId,
                      VendorName = vList.Name // 替换为Dto中对应供应商名称的属性名
                  }).ToList();

    // 直接传入result即可,无需重复ToList()
    return ResultModel<IEnumerable<PurchaseOrderHeaderDto>>.Create(result);
}

方案2:使用映射工具(如AutoMapper)

如果你项目中使用了AutoMapper,可以先查询出数据,再通过映射工具转换为Dto:

  1. 先配置AutoMapper映射规则(例如在Profile中):
public class PurchaseOrderProfile : Profile
{
    public PurchaseOrderProfile()
    {
        CreateMap<(PurchaseOrderHeader Po, Vendor Vendor), PurchaseOrderHeaderDto>()
            .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Po.Id))
            .ForMember(dest => dest.Date, opt => opt.MapFrom(src => src.Po.Date))
            .ForMember(dest => dest.VendorId, opt => opt.MapFrom(src => src.Po.VendorId))
            .ForMember(dest => dest.VendorName, opt => opt.MapFrom(src => src.Vendor.Name));
        // 或者直接从匿名类型映射,只要属性名匹配即可
    }
}
  1. 修改Handle方法:
// 注入IMapper
private readonly IMapper _mapper;
public Handler(IRepository<PurchaseOrderHeader> purchaseOrderHeaderRepository, IRepository<Vendor> vendorRepository, IMapper mapper)
{
    _purchaseOrderHeaderRepository = purchaseOrderHeaderRepository ?? throw new ArgumentNullException(nameof(purchaseOrderHeaderRepository));
    _vendorRepository = vendorRepository ?? throw new ArgumentNullException(nameof(vendorRepository));
    _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
}

public async Task<ResultModel<IEnumerable<PurchaseOrderHeaderDto>>> Handle(GetPurchaseOrderListQuery request, CancellationToken cancellationToken)
{
    var data = await _purchaseOrderHeaderRepository.GetAllAsync();
    var vendorList = await _vendorRepository.GetAllAsync();

    var queryResult = (from poList in data
                       join vList in vendorList on poList.VendorId equals vList.Id
                       select new { Po = poList, Vendor = vList }).ToList();

    // 通过AutoMapper转换为Dto集合
    var result = _mapper.Map<IEnumerable<PurchaseOrderHeaderDto>>(queryResult);

    return ResultModel<IEnumerable<PurchaseOrderHeaderDto>>.Create(result);
}

额外优化

原代码中result.ToList()是多余的,因为前面的LINQ查询已经调用了.ToList(),直接传入result即可避免不必要的集合复制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 09:47:45