Ho iniziato a utilizzare l'entità core e mi sono imbattuto in un problema. Sto usando automapper nel mio progetto e non so come popolare la mia tabella di join (BookAuthor).
In MVC ho lavorato con ICollections ma il core delle entità non supporta ancora il lavoro con molte e molte entità di relazione e ora devo lavorare con la tabella di join.
Domanda: Come posso mappare il mio Bookviewmodel al libro? Non so cosa dovrei fare con la mia lista di BookAuthors. Forse non dovrei popolarlo?
Ho provato qualcosa del genere ma non funziona.
CreateMap<BookViewModel, Book>()
.ForMember(b => b.BookAuthors, opt => opt.MapFrom(b => b.Authors.Select(a => new BookAuthor
{
AuthorId = a.AuthorId
}
Modelli (alcune proprietà rimosse per brevità)
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; }
}
La versione funzionante della mappatura
.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 })));
Ecco la configurazione di mappatura desiderata:
CreateMap<Book, BookViewModel>()
// Book -> BookViewModel
.ForMember(b => b.Authors, opt => opt.MapFrom(b => b.BookAuthors
.Select(ba => ba.Author)))
.ReverseMap()
// BookViewModel -> Book
.PreserveReferences()
.ForMember(b => b.BookAuthors, opt => opt.MapFrom(b => b.Authors
.Select(a => new { b.BookId, Book = b, a.AuthorId, Author = a })))
;
CreateMap<Author, AuthorViewModel>()
// Author -> AuthorViewModel
.ReverseMap()
// AuthorViewModel -> Author
;
La cosa più importante è rendersi conto che AutoMapper non richiede il tipo dell'espressione restituita da MapFrom
per abbinare il tipo della destinazione. Se non corrisponde, AutoMapper proverà a mappare il tipo restituito al tipo di destinazione utilizzando la mappatura corrispondente, se presente. Questo ti permette di riutilizzare i mapping.
Per convertire BookAuthor
in AuthorViewModel
, devi prima convertirlo in Author
(semplicemente estraendo la proprietà Author
) come se fosse una raccolta di Author
e lasciare che AM converta l' Author
in AuthorViewModel
usando la mappatura corrispondente.
Per convertire AuthorViewModel
da BookViewModel.Authors
a BookAuthor
, lo converti prima in un tipo anonomymous simile a BookAuthor
, ma con i corrispondenti tipi di proprietà Book
e Author
tipi ViewModel
e lascia AM convertirlo in BookAuthor
utilizzando i mapping corrispondenti. PreserveReferences()
viene utilizzato per evitare l'overflow dello stack dovuto al modello di riferimento circolare.