Загрузка вложенных свойств в Entity Framework Core - PullRequest
0 голосов
/ 31 мая 2018

Можно ли как-нибудь избежать использования Include и ThenInclude в EF Core?У меня есть эти модели и dtos:

Для книги:

  public partial class Book
   {
      public Book()
   {
     BookAuthors = new HashSet<BookAuthor>();
     BookCategories = new HashSet<BookCategory>();
     Reviews = new HashSet<Review>();
   }

  public int BookId { get; set; }
  public string Title { get; set; }
  ...
  public string ImageUrl { get; set; }

  public ICollection<BookAuthor> BookAuthors { get; set; }
  public ICollection<BookCategory> BookCategories { get; set; }
  public ICollection<Review> Reviews { get; set; }
 }

  public class BookDto
 {
   public int BookId { get; set; }
   public string Title { get; set; }
   ...
   public string ImageUrl { get; set; }
   public IList<AuthorDto> Authors { get; set; }
   public IList<CategoryDto> Categories { get; set; }
   public IList<ReviewDto> Reviews { get; set; }
}

Для автора:

public partial class Author
{
    public Author()
    {
        BookAuthors = new HashSet<BookAuthor>();
    }
    public int AuthorId { get; set; }
    public string AuthorName { get; set; }
    ...
    public ICollection<BookAuthor> BookAuthors { get; set; }
}

public class AuthorDto
{
  public int AuthorId { get; set; }
  public string AuthorName { get; set; }
  ...
  public IList<BookDto> Books { get; set; }
}

Для категории:

 public partial class Category
 {
    public Category()
    {
        BookCategories = new HashSet<BookCategory>();
    }

    public int CategoryId { get; set; }
    public string CategoryName { get; set; }
    public string Description { get; set; }
    public ICollection<BookCategory> BookCategories { get; set; }
  }

public class CategoryDto
{
  public int CategoryId { get; set; }
  public string CategoryName { get; set; }
  public string Description { get; set; }
  public IList<BookDto> Books { get; set; }
}

ИРецензия:

public partial class Review
{
    public int ReviewId { get; set; }
    public int BookId { get; set; }
    public int UserId { get; set; }
    public DateTime? Date { get; set; }
    public string Comments { get; set; }
    public decimal? Rating { get; set; }
    public Book Book { get; set; }
    public User User { get; set; }
}

public class ReviewDto
{
    public int ReviewId { get; set; }
    public int BookId { get; set; }
    public int UserId { get; set; }
    public DateTime? Date { get; set; }
    public string Comments { get; set; }
    public decimal? Rating { get; set; }
    public Book Book { get; set; }
    public User User { get; set; }
}

У меня есть это:

public IEnumerable<Book> GetAll()
{
  var books = _context.Book
        .Include(e => e.BookAuthors)
        .ThenInclude(a => a.Author)
        .Include(c => c.BookCategories)
        .ThenInclude(categ => categ.Category)
        .Include(r => r.Reviews)
        .AsNoTracking()
        .ToList();
  return books;
}

А потом в авторе:

public IEnumerable<Author> GetAll()
{
  var authors = _context.Author
        .Include(e => e.BookAuthors)
        .ThenInclude(b => b.Book)
        .ToList();
  return authors;
}

public Author GetById(int id)
{
  return _context.Author.Include("BookAuthors.Book").SingleOrDefault(x => 
  x.AuthorId == id);
}

Между книгами и авторами, книгами и категориями У меня есть много, чтобымного отношений, между Ревью и Книгами один ко многим.Мне это нужно, потому что в списке с книгами я также показываю имя автора, на странице сведений об авторе я показываю его книги и так далее.Я также использую AutoMapper и DTO.

То же самое для категорий, обзоров .. мой json с возвращенными данными становится очень большим, и загрузка данных на страницу занимает много времени, потому чтоимеет эту вложенную структуру.Что было бы лучшим решением для этого?

1 Ответ

0 голосов
/ 07 июня 2019

Есть способ сделать загрузку Eager.Я попробовал GroupJoin (выражение) .SelectMany (...).Это позволит вам загружаться до одного уровня, избегая круговой пересылки.Я покажу вам, как я его заархивировал, но с вашими моделями.

У вас есть:

 var books = _context.Book
    .Include(e => e.BookAuthors)
    .ThenInclude(a => a.Author)
    .Include(c => c.BookCategories)
    .ThenInclude(categ => categ.Category)
    .Include(r => r.Reviews)
    .AsNoTracking()
    .ToList();
 return books;

Кстати, вы не ставите модель BookAuthors.Итак, я предполагаю, что это структура:

var books = _context.Authors
        .GroupJoin(_context.Book,
                    t1 => new { IdAuthor = (Guid)t1.Id }, //where t1 = Authors, you should have IdAuthor in Book.
                    a => new { IdAuthor = (Guid)a.IdAuthor },     //where a = Book
                    (t1, a_join) => new { t1, a_join })
        .SelectMany(t1 => t1.a_join.DefaultIfEmpty(), (t1, a) => new { t1, a }) //.DefaultIfEmpty() = LEFT JOIN
        .Select(x => new AuthorBooksDTO
        {
            IdAutor = t1.t1.Id //please navegate t1 till VS shoows you which model is
            Books = t1.t1.a_join.toList() //navegate t1. a_join will be the list of books.
            ....
        })
        .ToList();

Конечно, для сборки требуется больше времени, но производительность невероятно улучшается.Дайте нам знать, если это работает для вас.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...