Automapper and Deep Loading

I have a question with regards to automapping entity framework objects which have been "deep loaded". I have a Project object which has a member called Tasks which is a collection. And each task has a member called Works which is a collection. When the Project is deep loaded, those Tasks and their Works member are all populated. It looks like this:

-- Project
    -- Task 1
        -- Work 1
        -- Work 2
    -- Task 2
        -- Work 3

I have figured out how to map 1 level deep using a resolver like this:

CreateMap<DataAccess.Task, Entities.Task>()
            .ForMember(obj => obj.Description, obj => obj.MapFrom(src => src.Description))
            .ForMember(obj => obj.Estimate, obj => obj.MapFrom(src => src.Estimate))
            .ForMember(obj => obj.Id, obj => obj.MapFrom(src => src.ID))
            .ForMember(obj => obj.ProjectId, obj => obj.MapFrom(src => src.Project))
            .ForMember(obj => obj.TaskName, obj => obj.MapFrom(src => src.TaskName))
            .ForMember(obj => obj.Visible, obj => obj.MapFrom(src => src.Visible))
            .ForMember(obj => obj.WorkItems, obj => obj.ResolveUsing<WorkItemsResolver>().FromMember(src => src.Works));

public class WorkItemsResolver : ValueResolver<EntityCollection<DataAccess.Work>, ICollection<Entities.Work>>
{
    #region Overrides of ValueResolver<List<Task>,List<Task>>

    protected override ICollection<Entities.Work> ResolveCore(EntityCollection<DataAccess.Work> source)
    {
        Mapper.EntitiesMapper entitiesMapper = new EntitiesMapper(); 
        return source.Select(wk => entitiesMapper.Map<Entities.Work>(wk)).ToList();
    }

    #endregion
}

However, I cannot figure out how to go 2 levels deep ie to be able to map a top level object (Project) and have it's child lists (and their child lists) also get mapped to their concommitant business objects.

Does anyone know if this is possible with Automapper?

Thanks


You should have a corresponding DataAccess object for each Entity object. You already have a Task mapping, now you need one for Work. Also, don't use separate ValueResolvers. You can do anything you need using the lambda overloads in ForMember.

CreateMap<DataAccess.Task, Entities.Task>()
    // when names match on both sides, there is no need to call ForMember
    //.ForMember(obj => obj.Description, obj => obj.MapFrom(src => src.Description))
    //.ForMember(obj => obj.Estimate, obj => obj.MapFrom(src => src.Estimate))
    //.ForMember(obj => obj.Id, obj => obj.MapFrom(src => src.ID))
    .ForMember(obj => obj.ProjectId, obj => obj.MapFrom(src => src.Project))
    //.ForMember(obj => obj.TaskName, obj => obj.MapFrom(src => src.TaskName))
    //.ForMember(obj => obj.Visible, obj => obj.MapFrom(src => src.Visible))
    .ForMember(obj => obj.WorkItems, obj => obj.ResolveUsing(src =>
        Mapper.Map<IEnumerable<DataAccess.Work>>(src.Works)))
;

CreateMap<DataAccess.Work, Entities.Work>()
    // only call ForMember on properties that don't map automatically
;

Since you created a map for your 2'nd level of depth in the object hierarchy, you can just call Mapper.Map in the ResolveUsing lambda overload.

链接地址: http://www.djcxy.com/p/37402.html

上一篇: AutoMapper:Int到String并返回

下一篇: 自动映射器和深度加载