Mehmet Ince
Mehmet Ince

Reputation: 4179

Automapper many to many mapping confusion

I have many to many relationship tables such as "User & Notification & UserNotification" and their entities, view models also.

There is only a difference between ViewModel and Entity classes. HasRead property is inside NotificationViewModel. How Can I map this entities to view models? I could not achieve this for HasRead property.

What I did so far is,

Mapping Configuration:

CreateMap<Notification, NotificationViewModel>();
CreateMap<User, UserViewModel>().ForMember(dest => dest.Notifications, map => map.MapFrom(src => src.UserNotification.Select(x => x.Notification)));

Notification class:

public class Notification : IEntityBase
{
    public Notification()
    {
        this.UserNotification = new HashSet<UserNotification>();
    }

    public int Id { get; set; }
    public string Header { get; set; }
    public string Content { get; set; }
    public System.DateTime CreateTime { get; set; }
    public bool Status { get; set; }

    public virtual ICollection<UserNotification> UserNotification { get; set; }
}

User Class

public class User : IEntityBase
{
    public User()
    {
        this.UserNotification = new HashSet<UserNotification>();
    }

    public int Id { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public string Email { get; set; }
    public string PhoneNumber { get; set; }
    public bool Status { get; set; }

    public virtual ICollection<UserNotification> UserNotification { get; set; }
}

UserNotification class:

public class UserNotification : IEntityBase
{
    public int Id { get; set; }
    public int UserId { get; set; }
    public int NotificationId { get; set; }
    public bool HasRead { get; set; }

    public virtual Notification Notification { get; set; }
    public virtual User User { get; set; }
}

UserViewModel class

public class UserViewModel : IValidatableObject
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public string Email { get; set; }
    public string PhoneNumber { get; set; }
    public bool Status { get; set; }

    public IList<NotificationViewModel> Notifications { get; set; }
}

NotificationViewModel class

public class NotificationViewModel
{
    public int Id { get; set; }
    public string Header { get; set; }
    public string Content { get; set; }
    public System.DateTime CreateTime { get; set; }
    public bool Status { get; set; }
    public bool HasRead { get; set; } // this is the difference
}

Upvotes: 0

Views: 478

Answers (1)

grek40
grek40

Reputation: 13438

In order to fix up the HasRead, maybe you can utilize the AfterMap(Action<TSource, TDestination> afterFunction) function. It's not as elegant as the rest of automapper, but it might work.

CreateMap<User, UserViewModel>()
    .ForMember(dest => dest.Notifications, map => map.MapFrom(src => src.UserNotification.Select(x => x.Notification)))
    .AfterMap((src, dest) =>
    {
        foreach (var notificationVM in dest.Notifications)
        {
            notificationVM.HasRead = src.UserNotification.Where(x => x.NotificationId == notificationVM.Id).Select(x => x.HasRead).FirstOrDefault();
        }
    });

Upvotes: 2

Related Questions