C# 防止AutoMapper在LINQ ProjectTo中将字符串视为集合
我要映射以下一组类(仅在一个方向上,从C# 防止AutoMapper在LINQ ProjectTo中将字符串视为集合,c#,automapper,C#,Automapper,我要映射以下一组类(仅在一个方向上,从Data*到Api*): //顶层 公共类数据实体 { 公共嵌套数据实体嵌套{get;set;} //…其他基本/复杂属性 } 公共类实体 { 公共嵌套实体嵌套{get;set;} //…其他基本/复杂属性 } //嵌套级别 公共类嵌套数据实体 { 公共字符串项{get;set;} } 公共类嵌套实体 { 公共IEnumerable项{get;set;} } 公共类子项 { //这里有一些属性。为了举例,不需要 } 映射在配置文件中配置,如下代码位所示:
Data*
到Api*
):
//顶层
公共类数据实体
{
公共嵌套数据实体嵌套{get;set;}
//…其他基本/复杂属性
}
公共类实体
{
公共嵌套实体嵌套{get;set;}
//…其他基本/复杂属性
}
//嵌套级别
公共类嵌套数据实体
{
公共字符串项{get;set;}
}
公共类嵌套实体
{
公共IEnumerable项{get;set;}
}
公共类子项
{
//这里有一些属性。为了举例,不需要
}
映射在配置文件中配置,如下代码位所示:
//映射配置文件
公共类MyCustomProfile:Profile
{
公共MyCustomProfile()
{
CreateMap();
CreateMap();
CreateMap()
.ConvertUsing();
}
}
//类型转换器定义
公共类TextToSubItemsConverter:
IT类型转换器
{
公共IEnumerable转换(
字符串数据项、IEnumerable API项、ResolutionContext上下文)
{
//实际上,反序列化并返回ApiSubItem[]
//这里只返回一些固定数组
返回新的ApiSubItem[]
{
新建ApiSubItem(),
新建ApiSubItem(),
新建ApiSubItem(),
};
}
}
//主要
公共课程
{
公共静态void Main(字符串[]args)
{
Mapper.Initialize(cfg=>
{
AddProfile();
});
assertConfigurationsValid();
DataEntity DataEntity=新的DataEntity()
{
嵌套=新的嵌套数据实体()
{
Items=“忽略的文本”,
},
};
//这张地图很好,没有问题
ApiEntity ApiEntity=Mapper.Map(数据实体);
IQueryable dataEntities=new[]{dataEntity}.AsQueryable();
//这将向ApiSubItem问题公开System.Char
ApiEntity apiEntityProjected=dataEntities.ProjectTo().First();
}
}
映射配置在启动时通过初始验证,但当需要实际映射时,我得到异常:
System.InvalidOperationException:缺少从System.Char到my.Anwhere.namespace.ApiSubItem的映射。使用Mapper.CreateMap创建
如果我完全省略了string
和IEnumerable
之间的配置,则初始验证会抱怨相同的上下文:
背景:
从System.Char类型映射到my.Anwhere.namespace.ApiSubItem
虽然当添加,它似乎没有拿起汽车制造商
映射发生在静态上下文中,通过ProjectTo()
调用DbSet
上的LINQ查询。我已经检查过转换器不需要任何依赖项,以防万一
AutoMapper是5.0.2,在ASP.NETCore1RTM下的MVCAPI web应用程序中运行
我已经检查了类似的问题,但没有运气。有人知道如何让这种场景工作吗?我想我不是第一个尝试(自动)从字符串映射到集合的人。助教
EDIT在示例中添加了失败案例和非失败案例
编辑2进一步搜索后,有人建议忽略该字段并在AfterMap()
中执行映射。使用此配置文件时,不会引发异常,但生成的项
字段为空:
CreateMap<DataEntity, ApiEntity>();
CreateMap<NestedDataEntity, NestedApiEntity>()
.ForMember(api => api.Items, options => options.Ignore())
.AfterMap((data, api) =>
{
api.Items = Mapper.Map<IEnumerable<ApiSubItem>>(data.Items);
});
CreateMap<string, IEnumerable<ApiSubItem>>()
.ConvertUsing<TextToSubItemsConverter>();
CreateMap();
CreateMap()
.ForMember(api=>api.Items,options=>options.Ignore())
.AfterMap((数据,api)=>
{
api.Items=Mapper.Map(data.Items);
});
CreateMap()
.ConvertUsing();
编辑3重新编写问题标题,使其更具体地用于投影我猜实际答案大致是“投影和转换器/分解器不能很好地结合在一起”。从AutoMapper wiki:
并非所有映射选项都可以支持,因为生成的表达式必须由LINQ提供程序解释。[……]
不支持:
- [……]
- 前/后地图
- 自定义解析器
- 自定义类型转换器
编辑解决方法:
在这个特定的场景中,我后来发现有一个中间DTO实体非常有用,它可以获取更多的字段,这对于最终的API实体来说不是必需的,但是对于业务逻辑来说仍然是必需的
在这样的DTO实体中,我将字符串
字段保留为数据实体
,因此我可以使用投影,让AutoMapper/LinqToSQL只从数据库中获取所需的字段
然后,在内存中已有的DTO实体和API实体之间,我可以应用第二个映射,它还利用了string==>IEnumerable
映射的自定义转换器。HTH您不能将字符串映射到集合,在这种情况下,您需要打包返回类型为字符串的items.propertyname。因为automapper在一对一映射中工作,所以你能做一个@PankajGupta吗?你能不能再告诉我一次,我不能得到它。@SamIam核心位在那里,现在我编辑了这个问题,添加了一个完整的示例。请让我知道,如果您认为有其他部分缺少@downvoter,请解释动机,以便至少改进问题