【问题标题】:ProjectTo with ITypeConverterProjectTo 与 ITypeConverter
【发布时间】:2022-08-02 21:55:19
【问题描述】:

我正在使用 Automapper 通过ProjectTo<>() 将数据库实体从实体框架映射到业务对象。现在我想将可空的十进制映射/投影到类类型,并且不想为每个对象中的每个属性指定这两种类型的手动映射,所以我决定使用自定义类型转换器,Automapper 会做工作。当decimal? 属性具有值时,它可以正常工作,但是当它为 null(并且 DB 表列允许 NULL)时,它会抛出一个异常,说“Sql Tree 中的 Null TypeMapping”,并且转换器的 Convert() 方法是根本没有调用。代码如下:

基本类类型和派生(众多之一)

public abstract class BaseUnit
{
    public decimal? DefaultValue { get; protected set; }
    public abstract ViewableUnit GetRequestedUnit(Unit unit);
}

public class Density : BaseUnit
{
    public Density()
    {
        this.DefaultValue = decimal.Zero;
    }
    
    public Density(decimal? densityInGperL)
    {   
        this.DefaultValue = densityInGperL;
    }

    public decimal? GramsPerLiter
    {
        get => this.DefaultValue;
        set => this.DefaultValue = value;
    }

    public decimal? GramsPerDeciliter
    {
        get => this.DefaultValue * 10;
        set => this.DefaultValue = value * 0.1m;
    }

    public override ViewableUnit GetRequestedUnit(Unit unit)
    {
        ...
    }
}

转换器和注册

public class DecimalUnitTypeConverter : ITypeConverter<decimal?, Density>
{
    public Density Convert(decimal? source, Density destination, ResolutionContext context)
    {
        return source.HasValue ? new Density(source.Value) : null;
    }
}

Mapper.CreateMap(typeof(decimal?), typeof(Density)).ConvertUsing(typeof(DecimalUnitTypeConverter));

数据库实体和 DTO

public class LabResult
{
    decimal? NumberResult { get; set; }
    ...
}

public class LabResultDto
{
    Density NumberResult { get; set; }

    public void CreateMappings(Profile configuration)
    {
        configuration.CreateMap<LabResult, LabResultDto>()
        .ForMember(
         dst => dst.NumberResult,
         opt =>
         {
             opt.PreCondition(src => src.NumberResult.HasValue); // does not have to be here, the outcome is the same
             opt.MapFrom(src => src.NumberResult);
         });
    }
}

和最终用途

dbContext.LabResults.AsNoTracking()
.Where(lab => lab.Id == request.Id)
.ProjectTo<LabResultDto>(this.configurationProvider)
.ToList();

我知道 Map 和 ProjectTo 的工作方式不同,但我认为这种类型的映射/投影是微不足道的,即使我告诉 Automapper 如何通过类型转换器进行操作。我错过了什么吗?感谢您提供任何帮助。

标签: c# asp.net-core entity-framework-core automapper-11


【解决方案1】:

由于类型转换器不适用于@Lucian Bargaoanu 发布的投影,因此我找到了解决方案。也许一般不适合所有人,但就我的目的而言,它运作良好。我刚刚声明了从decimal? 到我希望应用映射的任何类的普通映射,剩下的工作由 Automapper 完成。

this.CreateMap<decimal?, Density>()
.ForMember(
          dst => dst.GramsPerLiter,
          opt => opt.MapFrom(src => src));

Automapper 使用默认 ctor 创建 Density 类的实例,然后通过“默认”属性分配值。在这种情况下,属性GramsPerLiter 用作默认属性,其中所有类似密度的记录都统一映射到整个系统,如果需要,可以转换为不同的单位(kg/L、g/cm3、kg/m3 .. .)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-31
    • 2021-10-26
    相关资源
    最近更新 更多