使用AutoMapper和EF反向POCO生成器映射EF集合

时间:2016-01-27 21:46:22

标签: asp.net-mvc entity-framework automapper

我获得了一个首先使用EF数据库,EF反向POCO生成器和自动映射器的项目。我真的很难通过使用这三件来正确地建立多对多的关系,并且会感激任何帮助。

我的数据库中有以下表格:

+=================+    +==================+    +================+
|      Event      |    |   Event_Format   |    |     Format     |
+=================+    +==================+    +================+
| Id              |    | Id               |    | Id             |
| Title           |    | EventId          |    | Name           |
| Created         |    | FormatId         |    | Created        |
| CreatedBy       |    | Created          |    | CreatedBy      |
|                 |    | CreatedBy        |    |                |
+=================+    +==================+    +================+

这会在我的数据层中生成三个POCO类:

public class Event {
    public int Id { get; set; } // Id (Primary key)
    public string Title { get; set; } // Title
    public DateTime Created { get; set; } // Created
    public string CreatedBy { get; set; } // CreatedBy
    public virtual ICollection<EventFormat> EventFormats { get; set; } // Event_Format.FK_Event_Format_Event
}

public class EventFormat
{
    public int Id { get; set; } // Id (Primary key)
    public int EventId { get; set; } // EventId
    public int FormatId { get; set; } // FormatId
    public DateTime Created { get; set; } // Created
    public string CreatedBy { get; set; } // CreatedBy
    public virtual Event Event { get; set; } // FK_Event_Format_Event
    public virtual Format Format { get; set; } // FK_Event_Format_Format
}

public class Format
{
    public int Id { get; set; } // Id (Primary key)
    public string Name { get; set; } // Name
    public DateTime Created { get; set; } // Created
    public string CreatedBy { get; set; } // CreatedBy
    public virtual ICollection<EventFormat> EventFormats { get; set; } // Event_Format.FK_Event_Format_Format
}

在我的MVC项目中,我有一个事件和格式的视图模型(但不是因为它似乎不需要的EventFormats)。

public class Event.ViewModel
{
    public int Id { get; set; }
    public string Title { get; set; }
    public DateTime Created { get; set; }
    public string CreatedBy { get; set; }
    public List<Format.ViewModel> Formats { get; set; }
}
public class Format.ViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime Created { get; set; }
    public String CreatedBy { get; set; }
}

以下是Mapper个人资料:

protected internal class BookingProfile : Profile
{
    public new string ProfileName = "Admin_Booking";

    protected override void Configure()
    {
        CreateMap<Data.Models.Event, Models.Booking.WisconsinFilmFest.ViewModel>()
            .ForMember(dst => dst.Created, x => x.MapFrom(src => src.Created.ToLocalTime()))
            .ForMember(dst => dst.EventFormats, x => x.MapFrom(src => src.EventFormats.ToList()));
    }
}

protected internal class FormatProfile : Profile
{
    public new string ProfileName = "Admin_Format";

    protected override void Configure()
    {
        CreateMap<Data.Models.Format, Models.Format.ViewModel>()
            .ForMember(dst => dst.Created, x => x.MapFrom(src => src.Created.ToLocalTime()))
            .ForMember(dst => dst.Modified, x => x.MapFrom(src => src.Modified.ToLocalTime()));
    }
}

当我尝试使用AutoMapper将事件映射到Event.ViewModel时,它不起作用,因为EF返回EventFormat类型(因为有额外的列)。有没有办法告诉Automapper获取每个EventFormat项的格式,然后将它们映射到ViewModel上的Formats属性?

目前我正在做的是使用Automapper的AfterMap()功能,并循环遍历EventFormats中的每个项目以获取格式并将其添加到ViewModel的属性中,如下所示:

protected internal class BookingProfile : Profile
{
    public new string ProfileName = "Admin_Booking";

    protected override void Configure()
    {
        CreateMap<Data.Models.Event, Models.Booking.WisconsinFilmFest.ViewModel>()
            .ForMember(dst => dst.Created, x => x.MapFrom(src => src.Created.ToLocalTime()))
            .ForMember(dst => dst.EventFormats, x => x.Ignore())
            .AfterMap((src, dst) =>
                {
                    if(src.EventFormats.Any(x => x.Format.Deleted == null))
                    {
                        foreach(Data.Models.EventFormat ef in src.EventFormats)
                        {
                            dst.EventFormats.Add(Mapper.Map(ef.Format, new Models.Format.ViewModel()));
                        }
                    }
                });
}

这对我来说有些笨拙,我希望有更好的方法来做到这一点。

2 个答案:

答案 0 :(得分:2)

当然可以。指定AutoMapper应将Event.ViewModel.Formats映射到EventFormats.Select(ef => ef.Format)

Mapper.CreateMap<Format,Format.ViewModel>();
Mapper.CreateMap<Event,Event.ViewModel>()
    .ForMember(dest => dest.Formats, 
                  m => m.MapFrom(src => src.EventFormats.Select(ef => ef.Format)));

现在你可以做到

var result = db.Events.ProjectTo<Event.ViewModel>();

答案 1 :(得分:1)

您应该能够更新配置文件中的第一个映射,如下所示:

CreateMap<Data.Models.Event, Models.Booking.WisconsinFilmFest.ViewModel>()
        .ForMember(dst => dst.Created, x => x.MapFrom(src => src.Created.ToLocalTime()))
        .ForMember(dst => dst.Formats, x => x.MapFrom(src => src.EventFormats.Select(y => y.Format).ToList()));

按照目前的情况,配置文件告诉映射器将源类型的EventFormats属性投影到目标的EventFormats属性中,当它听起来像你真正想要的那样是将EventFormats.Format属性投影到Formats集合中。