自动映射从2个表映射到viewmodel

时间:2018-02-09 06:41:58

标签: c# automapper

我是C#和MVC的新手。

一些背景: UI屏幕将调用我的控制器返回“会议决议”列表,该列表由2个基础表连接。我创建了一个视图模型'MyNewViewModel',控制器将它返回给UI。 UI屏幕应该能够阅读&写入2个表。

创建Automapper以将2个基础表映射到此视图模型。但是,在使用此自动播放器时,我遇到了问题。有任何想法吗?谢谢!

我的自动播放器配置如下:

public static void MapToMeetingResolution(IMapperConfigurationExpression cfg)  
        {
            cfg.CreateMap<Table1, MyNewViewModel>()
                .ForMember(dest => dest.ResolutionNo, m => m.MapFrom(src => src.ResolutionNo))
                .ForMember(dest => dest.ResolutionCd, m => m.MapFrom(src => src.ResolutionCd))
                .ForMember(dest => dest.ResolutionDesc, m => m.MapFrom(src => src.ResolutionDesc))
            cfg.CreateMap<MyNewViewModel, Table1>()
                .ForMember(dest => dest.ResolutionNo, m => m.MapFrom(src => src.ResolutionNo))
                .ForMember(dest => dest.ResolutionCd, m => m.MapFrom(src => src.ResolutionCd))
                .ForMember(dest => dest.ResolutionDesc, m => m.MapFrom(src => src.ResolutionDesc))

            cfg.CreateMap<Table2, MyNewViewModel>()
                .ForMember(dest => dest.ElectionGroupId, m => m.MapFrom(src => src.ElectionGroupId))
                .ForMember(dest => dest.CorpActionId, m => m.MapFrom(src => src.CorpActionId))
                .ForMember(dest => dest.Election, m => m.MapFrom(src => src.Election))

            cfg.CreateMap<MyNewViewModel, Table2>()
                .ForMember(dest => dest.ElectionGroupId, m => m.MapFrom(src => src.ElectionGroupId))
                .ForMember(dest => dest.CorpActionId, m => m.MapFrom(src => src.CorpActionId))
                .ForMember(dest => dest.Election, m => m.MapFrom(src => src.Election))
        }

现在,使用映射器:

public async Task<MyNewViewModel> queryResolutionDetailsById(int id, string username)
{
var result1 = _context.Table1.Where(p => p.CorpActionId == id);
var result2 = _context.Table2.Where(p => p.CorpActionId == id && p.ElectedBy == username);
MyNewViewModel viewmodel1 = AutoMapper.Mapper.Map<MyNewViewModel>(result1);
viewmodel1 = AutoMapper.Mapper.Map<MyNewViewModel>(result2);
return viewmodel1;
}

代码在'AutoMapper.Mapper.Map'步骤中抛出错误。     AutoMapper.AutoMapperMappingException:'缺少类型映射配置或不支持的映射。'

但是,如果我将result1和result2更改为以下,则错误将消失。但这不是我想要的。

var result1 = _context.Table1.FirstOrDefault(p => p.CorpActionId == id);
var result2 = _context.Table2.FirstOrDefault(p => p.CorpActionId == id && p.ElectedBy == username);

2 个答案:

答案 0 :(得分:0)

您正在尝试将集合映射到单个项目。当您将LINQ查询从Where更改为FirstOrDefault时,您最终将单个项目映射到单个对象,因此它起作用。您应该按照以下方式编写它以使其正常工作

    public async Task<MyNewViewModel> queryResolutionDetailsById(int id, string username)
   {
     var result1 = _context.Table1.Where(p => p.CorpActionId == id);
     var result2 = _context.Table2.Where(p => p.CorpActionId == id && p.ElectedBy == username);
     IEnumerable<MyNewViewModel> viewmodel1 = AutoMapper.Mapper.Map<IEnumerable<MyNewViewModel>>(result1);
     // Even though syntactically correct, this line will overwrite
     // the values from the line above
     viewmodel1 = AutoMapper.Mapper.Map<IEnumerable<MyNewViewModel>>(result2);
     return viewmodel1;
   }

但是,上面的逻辑中存在一个错误。第二个赋值将覆盖第一个映射赋值中的值。因此,在第一次映射之后,您将不得不循环遍历第二个集合的结果并单独映射对象并将它们分配给相关项(您不能按顺序迭代它们,因为从两个查询返回的记录不一定匹配)。

此外,您的AutoMapper映射配置文件过于复杂,因为您不需要指定源和目标属性具有相同名称的映射。它可以用更简单的方式编写,如

public static void MapToMeetingResolution(IMapperConfigurationExpression cfg)  
{
   cfg.CreateMap<Table1, MyNewViewModel>()
      .ReverseMap();

  cfg.CreateMap<Table2, MyNewViewModel>()
     .ReverseMap();                
}

答案 1 :(得分:0)

让我们考虑 ResultDTO (表1,表2或更多的属性组合)

在自动映射器配置文件配置中

CreateMap<Table1, ResultDTO>().ReverseMap(); 
CreateMap<Table2, ResultDTO>().ReverseMap(); 

自动映射合并

 var resultDTO = new ResultDTO();
 resultDTO = Mapper.Map<Table1,ResultDTO>(_context.Table1.First());
 resultDTO = Mapper.Map<Table2,ResultDTO>(_context.Table2.First(),resultDTO);   // NOTE: PASS INITIALLY FILLED OBJECT (OTHER WISE IT WILL CONSIDERS NEW OBJECT AND IT SETS DEFAULT VALUES FOR REST OF ITS PROPERTIES)