Automapper: System.InvalidOperationException: 'Coalesce used with type that cannot be null'

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

尝试在单元测试中使用映射器配置文件时出现此错误

错误:

System.InvalidOperationException: 'Coalesce used with type that cannot be null'

堆栈跟踪:

 at System.Linq.Expressions.Expression.ValidateCoalesceArgTypes(Type left, Type right)
   at System.Linq.Expressions.Expression.Coalesce(Expression left, Expression right, LambdaExpression conversion)
   at System.Linq.Expressions.Expression.Coalesce(Expression left, Expression right)
   at AutoMapper.Execution.TypeMapPlanBuilder.CheckReferencesCache(Expression valueBuilder)
   at AutoMapper.Execution.TypeMapPlanBuilder.ConstructorMapping(ConstructorMap constructorMap)
   at AutoMapper.Execution.TypeMapPlanBuilder.CreateNewDestinationFunc()
   at AutoMapper.Execution.TypeMapPlanBuilder.CreateDestinationFunc()
   at AutoMapper.Execution.TypeMapPlanBuilder.CreateMapperLambda()
   at AutoMapper.TypeMap.CreateMapperLambda(IGlobalConfiguration configuration)
   at AutoMapper.TypeMap.Seal(IGlobalConfiguration configuration)
   at AutoMapper.MapperConfiguration.<.ctor>g__Seal|20_0()
   at AutoMapper.MapperConfiguration..ctor(MapperConfigurationExpression configurationExpression)
   at AutoMapper.MapperConfiguration..ctor(Action`1 configure)

图片:

如何复制:

  1. 创建一个 NUnit 项目(仅此而已)
  2. 替换代码:
using AutoMapper;

namespace UnitTestIssue
{
    public class TreeEntity
    {
        public Guid Id { get; set; }
        public string Name { get; set; }

        public InternalNodeEntity InternalNode { get; set; }

        public bool IsDeleted { get; set; }
    }

    public class InternalNodeEntity
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public List<InternalNodeEntity> InternalNodes { get; set; }
        public List<LeafNodeEntity> LeafNodes { get; set; }
        public bool IsDeleted { get; set; }
    }
   
    public class LeafNodeEntity
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public bool IsDeleted { get; set; }
    }

    public record struct TreeDto(Guid Id, string Name, InternalNodeDto Nodes, bool IsDeleted);
    public record struct InternalNodeDto(Guid Id, string Name, List<InternalNodeDto> InternalNodes, List<LeafNodeDto> LeafNodes, bool IsDeleted);
    public record struct LeafNodeDto(Guid Id, string Name, bool IsDeleted);
    public class Tests
    {
        private IMapper _mapper;

        [SetUp]
        public void Setup()
        {
            var config = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<LeafNodeDto, LeafNodeEntity>().ReverseMap();
                cfg.CreateMap<InternalNodeDto, InternalNodeEntity>().ReverseMap();
                cfg.CreateMap<TreeDto, TreeEntity>().ReverseMap();
            });
            config.AssertConfigurationIsValid();
            _mapper = config.CreateMapper();
        }

        [Test]
        public void Test1()
        {
            //doesn't matter, just to invoke [Setup]
            Assert.That(1, Is.EqualTo(1));
        }
    }
}
  1. csproj 包信息:
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>

    <IsPackable>false</IsPackable>
    <IsTestProject>true</IsTestProject>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="AutoMapper" Version="12.0.1" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
    <PackageReference Include="NodaTime" Version="3.1.9" />
    <PackageReference Include="NUnit" Version="3.13.3" />
    <PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
    <PackageReference Include="NUnit.Analyzers" Version="3.6.1">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="coverlet.collector" Version="3.2.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

</Project>

我尝试将可为空的 sytanx 与 Guid、字符串、InternalNode、LeafNode 一起使用,但似乎我无法破解它。

另外我觉得 Coalesce 在 List 和 List 之间转换失败?但不能确定这一点。

这是一个非常简单的项目,可以向一些学生传授 WebAPI 模式的基础知识,即

Api Controller Action --> Service (map dto -> entity) --> repository --> context (save/retireve to/from DB)

c# .net-core automapper .net-6.0
2个回答
0
投票

几乎可以肯定错误是因为您的顶级 DTO 需要是引用类型,而不是值类型。从您的

struct
中删除
record struct

关键字

0
投票

Automapper 似乎不支持记录结构映射,[mre] 将是:

record struct T1(int i);
record struct T2(int i);

[Test]
public void Test2()
{
    var config = new MapperConfiguration(cfg =>
    {
        cfg.CreateMap<T1, T2>();
       });
    config.AssertConfigurationIsValid();
}

您可以将所有内容更改为简单记录,然后以下内容将起作用:

[Test]
public void Test2()
{
    var config = new MapperConfiguration(cfg =>
    {
        cfg.CreateMap<LeafNodeDto, LeafNodeEntity>().ReverseMap();
        cfg.CreateMap<InternalNodeDto, InternalNodeEntity>().ReverseMap();
        cfg.CreateMap<TreeDto, TreeEntity>()
            .ForMember(entity => entity.InternalNode, expression => expression.MapFrom(dto => dto.Nodes))
            .ReverseMap();
    });
    config.AssertConfigurationIsValid();
}
© www.soinside.com 2019 - 2024. All rights reserved.