首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

Castle ActiveRecord 實戰(6):延遲載入與 Where 條件過濾——解決 N+1 問題與關聯查詢優化

     編輯:關於.NET

為什麼需要延遲載入?

預設情況下,Blog.Find(1) 會一次性載入該 Blog 及其所有關聯 Posts。若 Blog 有 1000 篇 Post,記憶體壓力大且多數情況不需要立即存取集合。延遲載入讓關聯集合在第一次被存取時才發出 SQL 查詢。

啟用延遲載入:一行屬性搞定

[HasMany(typeof(Post), Table = "posts", ColumnKey = "post_blogid", Lazy = true)]
public IList Posts { get; set; }

Lazy = true 指示 NHibernate 建立 Proxy 物件,首次呼叫 blog.Posts.Count 或迭代時才觸發 SELECT * FROM posts WHERE post_blogid = ?。

關鍵陷阱:Session 已關閉導致 LazyInitializationException

延遲載入需要有效的 NHibernate Session。若在 using (new SessionScope()) 區塊外存取集合,會拋出:

NHibernate.LazyInitializationException: Failed to lazily initialize a collection - no session

正確模式:

[Test]
public void TestLazyLoad() {
    using (new SessionScope()) { // 確保 Session 存活
        var blog = Blog.Find(8);
        var name = blog.Name; // 不觸發延遲載入
        var count = blog.Posts.Count; // 這裡才查詢 Posts
        Assert.AreEqual(2, count);
    }
}

Web 應用中通常在 HTTP Request 開始/結束處開啟/關閉 SessionScope(如 HttpModule)。

Where 子句:在映射層級過濾關聯集合

若只需載入特定條件的關聯物件(如分類為 "Castle" 的 Posts),可在 HasMany 指定 Where:

[HasMany(typeof(Post), Table = "posts", ColumnKey = "post_blogid", 
    Where = "post_categories = 'Castle'")]
public IList CastlePosts { get; set; }

注意:Where 寫的是**資料表欄位名**(post_categories),而非實體屬性名(Category)。

延遲載入 vs Where 子句:選型指南

特性延遲載入Where 子句
適用場景需完整集合,但非立即使用固定業務規則過濾子集(如只看已發布文章)
SQL 時機首次存取集合時載入主體時一併查詢(若非 Lazy)或首次存取時
靈活性高,運行時決定是否存取低,編譯期固定在映射屬性
N+1 風險迴圈中逐一存取會產生 N+1 查詢單一查詢取回過濾後集合

避免 N+1 問題的最佳實踐

  1. 批次抓取:在 HasMany 加上 BatchSize = 10,NHibernate 會用 IN 子句一次查詢多個主體的關聯集合。
  2. HQL 急切載入:from Blog b left join fetch b.Posts where b.Id = ?,單一查詢取回主體與集合。
  3. Criteria/QueryOver:使用 SetFetchMode("Posts", FetchMode.Eager) 程式化控制。

總結

延遲載入(Lazy=true)是優化關聯查詢的基礎利器,但必須配合 SessionScope 管理 Session 生命週期。Where 子句適合固定業務過濾規則,靈活查詢仍建議使用 HQL 或 Criteria。理解兩者機制差異,能有效避免 N+1 查詢與 Session 斷開異常。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved