Eager Loading

概念說明

在 Entity Framework Core 中,如果要將關聯資料載入查詢結果,可以使用 Eager Loading,它是將所有相關資料都載入記憶體中的方式。Eager Loading 可以使用 Include 方法來載入關聯資料。

以下是 Eager Loading 的基本語法:

var orders = _context.Orders.Include(o => o.OrderDetails).ToList();

這個查詢將會載入 Orders 和相關的 OrderDetails 資料。

範例說明

以下是 Microsoft 官方文件中有關 Eager Loading 的範例說明:

using (var context = new BloggingContext())
{
    var blogs = context.Blogs
        .Include(blog => blog.Posts)
            .ThenInclude(post => post.Author)
        .ToList();
}

這個範例會載入 Blogs、Blogs 的所有 Posts,以及每個 Post 的 Author 資料。

Lazy Loading

概念說明

在 Entity Framework Core 中,如果要使用 Lazy Loading,必須先啟用它。它是在需要時才載入相關資料的方式。可以使用 virtual 關鍵字來啟用 Lazy Loading。此外,必須在 DbContext 的 OnConfiguring 方法中啟用 Lazy Loading。

以下是啟用 Lazy Loading 的基本語法:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseLazyLoadingProxies()
        .UseSqlServer(myConnectionString);

使用 Lazy Loading 的時候,可以在需要時載入相關資料:

var orders = _context.Orders.ToList();

foreach (var order in orders)
{
    var orderDetails = order.OrderDetails.ToList();
}

範例說明

以下是 Microsoft 官方文件中有關 Lazy Loading 的範例說明:

using (var context = new BloggingContext())
{
    var blogs = context.Blogs.ToList();

    foreach (var blog in blogs)
    {
        // The Posts property will be lazily loaded here.
        if (blog.Posts.Count == 0)
        {
            blog.Posts.Add(
                new Post { Title = "Test Post", Content = "Test Content" });
        }
    }

    context.SaveChanges();
}

這個範例會載入 Blogs 資料,然後在需要時載入 Posts 資料。

Explicit Loading

概念說明

Explicit Loading是一種導入關聯實體的方式,透過Load()方法從DbContext實例中明確的導入特定的關聯實體,此時可以選擇一次導入一個或多個關聯實體。Explicit Loading通常用於需要導入單一實體的特定資訊,並且應用程式的需求比Eager Loading更為嚴格。

範例

以下是Explicit Loading的範例程式碼,採用Entity Framework Core 6的版本:

using (var context = new MyContext())
{
    var order = context.Orders.Find(1);

    // Load related OrderDetails for an order manually
    context.Entry(order)
        .Collection(b => b.OrderDetails)
        .Load();

    // Load related Product and Category for each OrderDetail
    foreach (var orderDetail in order.OrderDetails)
    {
        context.Entry(orderDetail)
            .Reference(b => b.Product)
            .Load();

        context.Entry(orderDetail.Product)
            .Reference(b => b.Category)
            .Load();
    }
}

在這個範例中,透過Find()方法取得OrderId為1的訂單,然後透過Collection()方法將關聯的OrderDetails導入,最後使用迴圈分別從每個OrderDetail實體中導入Product和Category實體。

該篇參考官方Loading Related Data