[英]How to map a list of related DTOs in a DTO: Nesting DTO mapping
假設您在大型數據庫中擁有書籍和作者的完全定義的關系,還有許多其他關系
public class Book
{
public int Id { get; set; }
public string Title { get; set; }
...
Public int AuthorId { get; set; }
Public Author Author { get; set; }
}
public class Author
{
public int Id { get; set; }
public int GroupId { get; set; }
public string Name { get; set; }
...
public List<Book> Books { get; set; }
...
}
並且在您的控制器中,您想返回一個作者列表,每個作者都包含使用DTO與他們相關聯的書籍的列表。
public class BookDTO
{
public int Id { get; set; }
public string Title { get; set; }
}
public class AuthorDTO
{
public int Id { get; set; }
public string Name { get; set; }
public List<BookDTO> Books { get; set; }
}
在DTO中生成DTO列表的正確方法是什么?
你能做這樣的事情嗎?
var author = from a in _context.authors.Where(a => a.groupId == someGroup)
select new AuthorDTO()
{
Id = a.Id,
Name = a.Name,
Books = (from b in a.Books
select new BookDTO()
{
Id = b.Id,
Title = b.Title
}).ToList()
};
或者也許是這樣?
var author = from a in _context.authors.Where(a => a.groupId == someGroup)
select new AuthorDTO()
{
Id = a.Id,
Name = a.Name,
Books = (from b in _context.books.Where(b => b.AuthorId == a.AuthorId)
select new BookDTO()
{
Id = b.Id,
Title = b.Title
}).ToList()
};
編輯:
為了更清楚一點,我在這里改寫並提出了我的問題:
我的意思是您可以執行以下操作:
var q = from b in Books
group b by b.Author into g
select new AuthorDTO
{
Name = g.Key.Name,
Books = g.Select(gi => new BookDTO { Title = gi.Title })
};
為此,不要將Books
聲明為List<BookDTO>
,而是將其聲明為IEnumerable<BookDTO>
。
您可以使用AutoMapper進行此操作。 您無需到處重復。 您將需要添加Profile
以便每次調用IMapper.Map
函數時映射都將起作用。
看這個例子
public class BookDTO
{
public int Id { get; set; }
public string Title { get; set; }
public class MapProfile:AutoMapper.Profile{
public MapProfile(){
CreateMap<Book,BookDTO>().ReverseMap();
}
}
}
public class AuthorDTO
{
public int Id { get; set; }
public string Name { get; set; }
public List<BookDTO> Books { get; set; }
public class MapProfile:AutoMapper.Profile{
public MapProfile(){
CreateMap<Author,AuthorDTO>()
.ForMember(dest.Id, opt => opt.MapFrom(src.Id))
.ForMember(dest.Name, opt => opt.MapFrom(src.Name))
.ForMember(dest.Books, opt => opt.MapFrom(src.Books));
}
}
}
現在,在您的控制器中,您需要注入IMapper
才能使用IMapper.Map<TSource, TDestination>
方法。
public class AuthorController : Controller{
private readonly IMapper mapper;
private readonly Context context;
public AuthorController(IMapper mapper, Context context){
mapper =mapper;
//...context=context;
}
public IActionResult Index(){
var authors = context.Author.Include(a=>a.Book).ToList();
var authorDTOs = mapper.Map<List<AuthorDTO>>(authors);
return View(authorDTOs);
}
}
這是Mapper配置文件示例。 配置文件類來自Automapper lib。
public class ApplicationServiceAutoMapperProfile : Profile
{
public ApplicationServiceAutoMapperProfile()
{
//Don't use ForMember method if you want to show Id's
CreateMap<Book, BookDTO>()
.ForMember(m => m.Id, opt => opt.Ignore());
CreateMap<Author, AuthorDTO>()
.ForMember(m => m.Id, opt => opt.Ignore());
}
}
這就是映射方法。GetAuthors方法返回映射的Dto。
public class CustomService {
private readonly IMapper _mapper;
private readonly DBContext _context;
public CustomService(IMapper mapper, DBContext context){
_mapper = mapper;
_context = context;
}
public IEnumerable<AuthorDTO> GetAuthors(){
//Automapper automaticaly maps authors's bookdto's also.
var authors = _context.authors.Where(a => a.groupId == 2).ToList();
return _mapper.Map<List<AuthorDTO>>(authors);
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.