在Entity Framework Core中加载嵌套属性

时间:2018-05-31 07:27:48

标签: c# entity-framework-core

有什么办法可以避免在EF Core中使用Include和ThenInclude吗? 我有这些模型和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);
}

在书籍和作者,书籍和类别之间我有很多关系,在Review和Books之间有一对多的关系。 我需要这个,因为在带有书籍的列表中我也会显示作者的姓名,在作者详细信息页面上我会显示他的书籍等等。我也使用AutoMapper和DTO。

同样的类别,Reviews.my json返回的数据变得非常大,并且需要花费大量时间将数据加载到页面中,因为它具有这种嵌套结构。这样做的最佳解决方案是什么?

1 个答案:

答案 0 :(得分:0)

有一种方法可以快速加载。我尝试了GroupJoin(expression).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();

可以肯定,构建需要花费更多时间,但是性能却得到了惊人的提高。 让我们知道它是否对您有用。