[英]AutoMapper ConvertUsing is not called
I have simple task: just map one class to another.我有一个简单的任务:只是 map 一个 class 到另一个。 For some fields I have complex logic, depends on 2 or more fields, so, I try to use
ConvertUsing
( https://docs.automapper.org/en/stable/Custom-type-converters.html )对于某些字段,我有复杂的逻辑,取决于 2 个或更多字段,因此,我尝试使用
ConvertUsing
( https://docs.automapper.org/en/stable/Custom-type-converters.html )
I use AutoMapper 10.0.0我使用 AutoMapper 10.0.0
My code is:我的代码是:
Source class:来源 class:
public class DeviceStatusHistory
{
public DeviceStatusHistory()
{
DateChange = DateTime.UtcNow;
}
public int Id { get; set; }
public int DeviceId { get; set; }
public virtual Device Device { get; set; }
public int? RequestId { get; set; }
public virtual DeviceManagementRequest Request { get; set; }
public DeviceStatus OldStatus { get; set; }
public DeviceStatus NewStatus { get; set; }
public string Notes { get; set; }
public DateTime DateChange { get; set; }
}
DTO class: DTO class:
public class DeviceChangeStatusDto
{
public int DeviceId { get; set; }
public string CarrierName { get; set; }
public string DeviceName { get; set; }
public string DeviceIMEI { get; set; }
public string OldStatus { get; set; }
public string NewStatus { get; set; }
public string Reason { get; set; }
public DateTime DateChange { get; set; }
}
and Automapper class:和自动映射器 class:
public class AutoMapperEfDeviceManagement : AutoMapper.Profile
{
public AutoMapperEfDeviceManagement()
{
CreateMap<DeviceStatusHistory, DeviceChangeStatusDto>().ConvertUsing<DeviceChangeStatusConverter>();
}
}
where DeviceChangeStatusConverter
is defined as:其中
DeviceChangeStatusConverter
定义为:
public class DeviceChangeStatusConverter : ITypeConverter<DeviceStatusHistory, DeviceChangeStatusDto>
{
public DeviceChangeStatusDto Convert(DeviceStatusHistory source, DeviceChangeStatusDto destination, ResolutionContext context)
{
destination = new DeviceChangeStatusDto
{
CarrierName = source.Device.CarrierId.HasValue ? source.Device.Carrier.Name : null,
DeviceId = source.DeviceId,
DateChange = source.DateChange,
DeviceIMEI = source.Device.IMEI,
DeviceName = source.Device.GetFriendlyDetailedName(),
NewStatus = CommonHelper.SplitByWords(source.NewStatus.ToString())
};
// some complex logic here
return destination;
}
}
but when I try to map it:但是当我尝试 map 时:
var list = _context.DeviceStatusHistory
.Where(a => ((int)a.NewStatus < 100) && a.DateChange.Date == date.Date)
.ProjectTo<DeviceChangeStatusDto>(_mapperConfig)
.ToList();
where _mapperConfig
is:其中
_mapperConfig
是:
_mapperConfig = new MapperConfiguration(cfg =>
{
cfg.AddProfile<AutoMapperEfDeviceManagement>();
});
It maps looks like it was declared simple as:它映射看起来像被声明为简单:
CreateMap<DeviceStatusHistory, DeviceChangeStatusDto>();
so, only the same properties are mapped, converter is not called (debugger says the same).所以,只有相同的属性被映射,转换器没有被调用(调试器说同样的)。 What is wrong?
怎么了?
ADDED:添加:
approach like:方法如:
CreateMap<DeviceStatusHistory, DeviceChangeStatusDto>()
.ConvertUsing((source, destination) =>
{
destination.CarrierName = source.Device.CarrierId.HasValue ? source.Device.Carrier.Name : null;
does not work too也不行
TL;DR TL;博士
It is not a bug, it's a known limitation.这不是错误,而是已知的限制。 Basically AutoMapper can't convert some custom method into SQL (or translate it into the form which will allow your ORM to translate that into SQL) so it can't use your type converter in
ProjectTo
.基本上 AutoMapper 无法将某些自定义方法转换为 SQL (或将其转换为允许您的 ORM 将其转换为 SQL 的形式),因此它不能在
ProjectTo
中使用您的类型转换器。
A little bit more details:更多细节:
From thedocumentation :从文档中:
The
.ProjectTo<OrderLineDTO>()
will tellAutoMapper
's mapping engine to emit aselect
clause to theIQueryable
that will inform entity framework that it only needs to query theName
column of theItem
table, same as if you manually projected yourIQueryable
to anOrderLineDTO
with aSelect
clause..ProjectTo<OrderLineDTO>()
将告诉AutoMapper
的映射引擎向IQueryable
发出select
子句,该子句将通知实体框架它只需要查询Item
表的Name
列,就像您手动投影您的IQueryable
到带有Select
子句的OrderLineDTO
。
And from Custom Type Conversion section:并来自自定义类型转换部分:
Occasionally, you need to completely replace a type conversion from a source to a destination type.
有时,您需要完全替换从源类型到目标类型的类型转换。 In normal runtime mapping, this is accomplished via the
ConvertUsing
method.在正常的运行时映射中,这是通过
ConvertUsing
方法完成的。 To perform the analog in LINQ projection, use theConvertUsing
method:cfg.CreateProjection<Source, Dest>().ConvertUsing(src => new Dest { Value = 10 });
要在 LINQ 投影中执行模拟,请使用
ConvertUsing
方法:cfg.CreateProjection<Source, Dest>().ConvertUsing(src => new Dest { Value = 10 });
The expression-basedConvertUsing
is slightly more limited thanFunc
-basedConvertUsing
overloads as only what is allowed in anExpression
and the underlying LINQ provider will work.基于表达式的
ConvertUsing
比基于Func
的ConvertUsing
重载稍受限制,因为只有Expression
中允许的内容和基础 LINQ 提供程序才能工作。
And Supported mapping options :和支持的映射选项:
Not all mapping options can be supported, as the expression generated must be interpreted by a LINQ provider.
并非所有映射选项都可以支持,因为生成的表达式必须由 LINQ 提供程序解释。 Only what is supported by LINQ providers is supported by AutoMapper:
AutoMapper 仅支持 LINQ 提供程序支持的内容:
- MapFrom (Expression-based)
MapFrom(基于表达式)
- ConvertUsing (Expression-based)
ConvertUsing(基于表达式)
- Ignore
忽视
- NullSubstitute
空替换
- Value transformers
价值转换器
- IncludeMembers
包括成员
Not supported:
不支持:
- Condition
健康)状况
- SetMappingOrder
设置映射顺序
- UseDestinationValue
使用目标值
- MapFrom (Func-based)
MapFrom(基于函数)
- Before/AfterMap
之前/之后地图
- Custom resolvers
自定义解析器
- Custom type converters
自定义类型转换器
- ForPath
路径
- Value converters
价值转换器
- Any calculated property on your domain object
您域 object 上的任何计算属性
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.