I've started using entity core and I ran into one problem. I'm using automapper in my project and don't know how to populate my join table(BookAuthor).
In MVC I worked with ICollections but entity core does not yet support working with many to many relationship entities and now I have to work with join table.
Question: How can i map my Bookviewmodel to the Book? I don't know what should I do with my BookAuthors list. Maybe I shouldn't populate it?
I tried something like that but it's not working.
CreateMap<BookViewModel, Book>()
.ForMember(b => b.BookAuthors, opt => opt.MapFrom(b => b.Authors.Select(a => new BookAuthor
{
AuthorId = a.AuthorId
}
Models(some properties removed for brevity)
public class Book
{
public int BookId { get; set; }
public List<BookAuthor> BookAuthors { get; set; }
}
public class Author
{
public int AuthorId { get; set; }
public string AuthorName { get; set; }
public List<BookAuthor> BookAuthors { get; set; }
}
public class BookAuthor
{
public int BookId { get; set; }
public Book Book { get; set; }
public int AuthorId { get; set; }
public Author Author { get; set; }
}
public class BookViewModel
{
public int BookId { get; set; }
public virtual List<AuthorViewModel> Authors { get; set; }
}
public class AuthorViewModel
{
public int AuthorId { get; set; }
public string AuthorName { get; set; }
}
public class Library : DbContext
{
public DbSet<Book> Books { get; set; }
public DbSet<Author> Authors { get; set; }
}
The working version of the mapping
.ForMember(dto => dto.Authors, opt => opt.MapFrom(b => b.BookAuthors.Select(a=>a.Author).ToList()));
CreateMap<List<BookAuthor>, List<AuthorViewModel>>();
.PreserveReferences()//don't forget about this row or you will get an error
.ForMember(b => b.BookAuthors, opt => opt.MapFrom(b => b.Authors
.Select(a => new { b.BookId, Book = b, a.AuthorId, Author = a })));
Here is the desired mapping configuration:
The most important thing is to realize that AutoMapper does not require the type of the returned expression from
MapFrom
to match the type of the destination. If it doesn't match, then AutoMapper will try to map the returned type to the destination type using the corresponding mapping if any. This allows you to reuse the mappings.In order to convert
BookAuthor
toAuthorViewModel
, you first convert it toAuthor
(by simply extracting theAuthor
property) like if it was a collection ofAuthor
, and let AM convert theAuthor
toAuthorViewModel
using the corresponding mapping.In order to convert
AuthorViewModel
fromBookViewModel.Authors
toBookAuthor
, you convert it first to anonomymous type similar toBookAuthor
, but with correspondingBook
andAuthor
property types beingViewModel
types and let AM convert it toBookAuthor
using corresponding mappings.PreserveReferences()
is used to avoid stack overflow due to circular reference model.