如何有效地使用Entity Framework Core?

Yur*_* N. 1 c# entity-framework entity-framework-core

我们来看看简单的类示例:

public class Book
{
    [Key]
    public string BookId { get; set; }
    public List<BookPage> Pages { get; set; }
    public string Text { get; set; }
} 

public class BookPage
{
    [Key]
    public string BookPageId { get; set; }
    public PageTitle PageTitle { get; set; }
    public int Number { get; set; }
}

public class PageTitle
{
    [Key]
    public string PageTitleId { get; set; }
    public string Title { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

所以,如果我想获得所有PageTitiles,如果我只知道BookId,我需要写一些包含,如下所示:

using (var dbContext = new BookContext())
{
    var bookPages = dbContext
    .Book
    .Include(x => x.Pages)
    .ThenInclude(x => x.PageTitle)//.ThenInclude(x => x.Select(y => y.PageTitle)) Shouldn't use in EF Core
    .SingleOrDefault(x => x.BookId == "some example id")
    .Pages
    .Select(x => x.PageTitle);
}
Run Code Online (Sandbox Code Playgroud)

如果我想让PageTitles与其他书籍连接,我需要再次重写这个方法,除了BookId之外没有任何改变!这是使用数据库的非常低效的方法,在这个例子中我有3个类,但是如果我有数百个类,嵌套到非常深的层次,那么工作会非常缓慢和不舒服.

我应该如何组织使用我的数据库,以避免许多包含和冗余查询?

D S*_*ley 5

问题1:我Includes每次都要添加一堆.

好吧,由于您必须在EF中明确包含相关数据,因此无法解决这个问题,但您可以轻松创建扩展方法以使其更清晰:

public static IQueryable<Book> GetBooksAndPages(this BookContext db)
{
    return db.Book.Include(x => x.Pages);
}

public static IQueryable<Book> GetBooksAndPagesAndTitles(this BookContext db)
{
    return GetBooksAndPages(db).ThenInclude(p => p.PageTitle)

}
Run Code Online (Sandbox Code Playgroud)

然后你可以这样做:

var bookPages = dbContext
    .GetBooksAndPagesAndTitles()
    .SingleOrDefault(x => x.BookId == "some example id")
    .Pages
    .Select(x => x.PageTitle);
Run Code Online (Sandbox Code Playgroud)

问题2:我必须多次为不同的ID编写此查询.

为什么不将它重构为带bookId参数的方法?

public IEnumerable<PageTitle> GetPageTitlesForBook(BookContext dbContext, int bookId)
{
    return dbContext
        .GetBooksAndPagesAndTitles()
        .SingleOrDefault(x => x.BookId == bookId)
        .Pages
        .Select(x => x.PageTitle);
}
Run Code Online (Sandbox Code Playgroud)

底线 - 如果您发现自己多次编写相同的内容,那么这是将代码重构为可重复使用的较小方法的绝佳机会.