简体   繁体   中英

Automapper many to many map fields from join

I am using Asp.net core, EF Core and Automapper. I have a many to many (kind of, in EF Core its necessary to use a join table for this) and am having trouble mapping an additional field in the join table to the related collection inside the DTO I am returning.

These are my entities (abbreviated):

Event entity:

public class Event
{
   public int Id { get; set; }
   public string Title { get; set; }
   public ICollection<EventAttendee> Attendees { get; set; }
}

AppUser entity:

public class AppUser : IdentityUser<int>
{
    public string PhotoUrl { get; set; }
    public ICollection<EventAttendee> AttendingEvents { get; set; }
}

EventAttendee entity:

public class EventAttendee
{
    public int AppUserId { get; set; }
    public AppUser AppUser { get; set; }
    public int EventId { get; set; }
    public Event Event { get; set; }
    public DateTime DateJoined { get; set; }
}

EventToReturnDto:

public class EventToReturnDto
{
    public int Id { get; set; }
    public string Title { get; set; }
    public ICollection<AttendeeDto> Attendees { get; set; }
}

AttendeeDto:

public class AttendeeDto
{
    public int Id { get; set; }
    public string UserName { get; set; }
    public DateTime DateJoined { get; set; }
}

Automapper profile:

public class MappingProfile : Profile
{
    public MappingProfile()
    {
        CreateMap<AppUser, AttendeeDto>();
        CreateMap<EventAttendee, AttendeeDto>();
        CreateMap<Event, EventToReturnDto>()
            .ForMember(dest => dest.Attendees,
                opt => opt.MapFrom(x => x.Attendees.Select(y => y.AppUser).ToList()));
    }    
}

Query:

var events = await _context.Events
    .Include(a => a.Attendees).ThenInclude(x => x.AppUser)
    .OrderBy(e => e.Date)
    .AsNoTracking()
    .ToListAsync(cancellationToken);

var eventsToReturn = _mapper.Map<List<EventToReturnDto>>(events); 

This results in the following output (I at least get the user information) but I can't figure out how to get the 'DateJoined' property from the EventAttendee into the collection of Attendees returned and just get the default date as follows:

{
    "id": 2,
    "title": "Event 2",
    "attendees": [
        {
            "id": 4,
            "userName": "Dave",
            "dateJoined": "0001-01-01T00:00:00"
        },
        {
            "id": 3,
            "userName": "Jane",
            "dateJoined": "0001-01-01T00:00:00"
        }
    ]
},

How would I go about creating the mapping to output the DateJoined property?

Thanks, James

First of all, you don't need both of these lines:

CreateMap<AppUser, AttendeeDto>();
CreateMap<EventAttendee, AttendeeDto>();

Because of your mapping instructions for the event, you are actually just mapping the AppUser but skip the EventAttendee completely. That is also why you are not able to get the DateJoined property.

Instead, you should map the event just to the event DTO and then make a custom mapping for the EventAttendee :

CreateMap<EventAttendee, AttendeeDto>()
   .ForMember(d => d.Id, o => o.MapFrom(s => s.AppUserId))
   .ForMember(d => d.UserName, o => o.MapFrom(s => s.AppUser.UserName))
   .ForMember(d => d.DateJoined, o => o.MapFrom(s => s.DateJoined));
CreateMap<Event, EventToReturnDto>();

So now, inside the event mapping, you are mapping the EventAttendee collection to an AttendeeDto collection, so you just need to set up the mapping for that. And within that, you can simply use navigation properties to access related entities.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM