C# 中的N+1問題

目錄

含義

影響

避免方法

1.?立即加載(Eager Loading)

2.?顯式加載(Explicit Loading)

3.?投影(Projection)

4.?批處理查詢

5.?禁用延遲加載


含義

N+1 問題?是 ORM(對象關系映射)框架(如 Entity Framework)中常見的性能問題,指:

  1. 1 次查詢?獲取主對象列表(如獲取所有客戶)。

  2. N 次額外查詢?為每個主對象單獨加載關聯數據(如為每個客戶查詢其訂單)。
    總查詢次數 =?1(初始查詢) + N(關聯數據查詢)

foreach (var id in productIds)
{// 每次循環都執行異步查詢var product = await dbContext.Products.Where(p => p.Id == id).FirstOrDefaultAsync();if (product != null){Console.WriteLine($"找到產品: {product.Name}");}
}

上面的代碼都會產生N+1問題 每一次循環都會執行異步的查詢操作 會降低性能

// 1. 查詢所有客戶(1 次查詢)
var customers = dbContext.Customers.ToList();foreach (var customer in customers)
{// 2. 為每個客戶單獨查詢訂單(N 次查詢)var orders = customer.Orders.ToList(); 
}

若?customers?有 100 條數據,將執行?101 次查詢(1 + 100)

影響
  • 性能瓶頸

    • 大量數據庫往返(網絡延遲 + 查詢解析開銷)。

    • 當 N 較大(如 1000+)時,響應時間顯著增加。

  • 數據庫壓力

    • 高并發場景下可能導致數據庫連接池耗盡。

  • 可伸縮性問題

    • 應用難以水平擴展(數據庫成為瓶頸)。

避免方法

1.?立即加載(Eager Loading)

使用?Include?一次性加載關聯數據(生成?JOIN?語句)。

var customers = dbContext.Customers.Include(c => c.Orders) // 一次性加載所有訂單.ToList();

執行過程

  • 生成單條 SQL:SELECT * FROM Customers JOIN Orders ...

  • 僅 1 次數據庫查詢

2.?顯式加載(Explicit Loading)

在單次操作中批量加載關聯數據(避免循環內查詢)。

var customers = dbContext.Customers.ToList();// 批量加載所有客戶的訂單(1 次查詢)
dbContext.Entry(customers).Collection(c => c.Orders).Load();
3.?投影(Projection)

通過?Select?僅查詢所需字段(自動處理關聯數據)。

var result = dbContext.Customers.Select(c => new {CustomerName = c.Name,Orders = c.Orders.Select(o => o.Amount).ToList()}).ToList();

優點

  • 生成高效 SQL(避免?SELECT *)。

  • 無額外查詢。

4.?批處理查詢

  • 批量預加載數據

  • 使用內存查詢替代循環內的數據庫查詢

手動合并查詢(如使用?WHERE IN?語句):

// 異步獲取所有數據
var items = await dbContext.Products.Where(p => p.Price > 100).ToListAsync();// 同步遍歷已獲取的數據
foreach (var item in items)
{Console.WriteLine($"產品: {item.Name}, 價格: {item.Price}");
}
var customerIds = customers.Select(c => c.Id).ToList();
var allOrders = dbContext.Orders.Where(o => customerIds.Contains(o.CustomerId)).ToList();// 內存中關聯數據
foreach (var customer in customers)
{customer.Orders = allOrders.Where(o => o.CustomerId == customer.Id).ToList();
}
5.?禁用延遲加載

在 ORM 中關閉延遲加載,強制開發者主動處理關聯數據。

// Entity Framework Core 配置
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{optionsBuilder.UseLazyLoadingProxies(false); // 禁用延遲加載
}
  • 代碼審查

    • 警惕循環內的?DbContext?查詢操作。

分頁處理

  • 當 N 極大時,分頁加載主數據(如?Take(100)

關鍵原則減少數據庫往返次數,用 1~2 次復雜查詢替代 N+1 次簡單查詢。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/95949.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/95949.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/95949.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

國內多光譜相機做得好的廠家有哪些?-多光譜相機品牌廠家

多光譜相機是一種能夠同時捕捉多個特定波段的光譜信息,這些波段覆蓋可見光、近紅外以及短波紅外等區域。廣泛應用于遙感、農業、環境監測、工業檢測、安防等領域。近年來,我國在多光譜技術領域取得了顯著進步,涌現出一批技術實力強、產品性能…

如何用外部電腦訪問本地網頁?

之前本來說用內網穿透工具來查看完成這個工具,結果感覺各種不符合心意,突然發現有更簡單的方法。如果想讓兩臺電腦在 同一局域網 內都能訪問運行在 http://localhost:5174/ 上的項目,而不需要使用內網穿透工具,可以通過以下方法實…

PromptPilot — AI 自動化任務的下一個環節

作者:陳大魚頭 github:https://github.com/KRISACHAN 郵箱:chenjinwen77@gmail.com PromptPilot 體驗地址:https://promptpilot.volcengine.com/ 前言 如果大家有關注 AI 相關新聞的話,一定會知道在 2025 年 6 月 11 日火山引擎 FORCE 原動力大會上,豆包大模型 1.6 系列…

[Responsive theme color] 動態更新 | CSS變量+JS操控 | 移動端-漢堡菜單 | 實現平滑滾動

第3章:CSS變量操控 歡迎回來🐻??? 通過前兩章,我們掌握了 動態主題定制 的交互邏輯,以及 色彩工具函數 如何實現色值格式轉換。 本章將揭示技術拼圖的最后一塊:CSS變量動態操控,解析JavaScript如何實…

數學建模 15 邏輯回歸與隨機森林

邏輯回歸(用于分類)用途:通過已有數據,計算出線性方程的參數w后,可以用于預測某一個物品屬于某一類的概率,[0,1];求解思想:邏輯回歸通過最大似然估計(Maximum Likelihood Estimation…

衡石使用指南嵌入式場景實踐之儀表盤嵌入

應用展示交互 應用集市展示應用時會與儀表盤、圖表進行交互操作,主要包括去分析、保存當前過濾快照、字段設置、刷新、全屏、嵌入、導出等功能。 保存當前過濾快照 儀表盤展示數據時往往使用過濾器來查看不同場景下的分析數據。用戶從一種場景切換到另一種場景&a…

Qt | 四種方式實現多線程導出數據功能

前言 在以往的項目開發中,在很多地方用到了多線程。針對不同的業務邏輯,需要使用不同的多線程實現方法,來達到優化項目的目的。本文記錄下在Qt開發中用到的多線程技術實現方法,以導出指定范圍的數字到txt文件為例,展示…

運放的學習筆記以及一些用法的個人看法

負反饋形成了虛短。 你的輸出會對-極產生一個向上的電壓,當你的-的時候就兩邊相等了,這個時候就輸出就不變了,也就是負反饋調節,調節了左邊的電壓差 如果你的右邊輸出已經達到了12v或者0v這個時候你就飽和了,這個時候…

MySQL的三大范式:

目錄 鍵和相關屬性的概念: 第一范式: 第二范式: 第三范式: 總結: 反范式化: 在關系型數據庫中,關于數據表設計的基本原則,規則就稱為范式。 范式是關系數據庫理論的基礎&…

如何解決pip安裝報錯ModuleNotFoundError: No module named ‘imageio’問題

【Python系列Bug修復PyCharm控制臺pip install報錯】如何解決pip安裝報錯ModuleNotFoundError: No module named ‘imageio’問題 摘要 在Python開發過程中,尤其是使用PyCharm等IDE時,遇到pip install報錯是一個常見的問題,尤其是在執行安裝…

2025年高效能工程項目管理軟件推薦榜單:AI重構工程進度可視化與資源動態調度體系

在工程行業數字化深度變革的2025年,項目管理正面臨前所未有的挑戰與機遇。權威數據顯示,68%的工程項目因進度追蹤滯后導致交付延期,超半數企業因數據孤島陷入跨部門協同效率低下的困境,而資源錯配造成的隱性成本損失高達年度預算的15%。隨著AI決策引擎、BIM全流程融合、IoT物聯…

豆包 Java的23種設計模式

Java的23種設計模式是軟件開發中常用的設計思想總結,根據用途可分為三大類:創建型、結構型和行為型。 一、創建型模式(5種) 用于處理對象創建機制,隱藏創建邏輯,使程序更靈活。 單例模式:保證一…

Redis7學習--詳解哨兵,文件配置、主客觀下線

目錄 一、前言 二、哨兵 1、是什么? 2、哨兵的功能 3、案例演示 Redis Sentinel 架構 配置說明 哨兵配置文件 主從配置文件 主節點宕機后各節點狀態 主從切換后配置文件的自動調整 4、哨兵運行流程和選舉原理 SDOWN主觀下線 ODOWN客觀下線 選出新的主節…

Android 項目:畫圖白板APP開發(二)——歷史點、數學方式推導點

上一章我們講解了如何繪制順滑、優美的曲線,為本項目的繪圖功能打下了基礎。本章我們將深入探討兩個關鍵功能的實現:歷史點和數學方式推導點。這些功能將大幅提升我們白板應用的專業性和用戶體驗。一、History點之前在onTouchEvent中獲取的MotionEvent&a…

25. for 循環區別

1. 基本 for 循環 for (let i 0; i < 10; i) {console.log(i); }特點&#xff1a; 適用于已知循環次數的情況使用數字索引進行迭代可以精確控制循環過程性能最好&#xff0c;開銷最小 2. for…in 循環 // 數組示例 for (let i in [1, 2, 3]) {console.log(i, typeof i); //…

Trae 輔助下的 uni-app 跨端小程序工程化開發實踐分享

大家好&#xff0c;我是不如摸魚去&#xff0c;歡迎來到我的AI編程分享專欄。 這次來分享一下&#xff0c;我使用 Trae 作為主要AI編程工具&#xff0c;開發 uni-app 跨平臺小程序的完整實踐經驗。我在實際的開發過程中&#xff0c;探索了 Trae 輔助開發的具體應用場景和效果&…

Vue3 + Element Plus 人員列表搜索功能實現

設計思路使用Element Plus的el-table組件展示人員數據 在姓名表頭添加搜索圖標按鈕 點擊按鈕彈出搜索對話框 在對話框中輸入姓名進行搜索 實現搜索功能并高亮匹配項下面是完整的實現代碼&#xff1a;<!DOCTYPE html> <html lang"zh-CN"> <head><…

告別手動優化!React Compiler 自動記憶化技術深度解析

概述 React Compiler 是 React 團隊開發的一個全新編譯器&#xff0c;目前處于 RC&#xff08;Release Candidate&#xff09;階段。這是一個僅在構建時使用的工具&#xff0c;可以自動優化 React 應用程序&#xff0c;無需重寫任何代碼即可使用。 核心特性 自動記憶化優化 …

【從零開始學習Redis】項目實戰-黑馬點評D2

商戶查詢緩存 為什么用緩存&#xff1f;作用模型緩存流程按照流程編寫代碼如下 Service public class ShopServiceImpl extends ServiceImpl<ShopMapper, Shop> implements IShopService {Resourceprivate StringRedisTemplate stringRedisTemplate;Overridepublic Resul…

后端Web實戰-MySQL數據庫

目錄 1.MySQL概述 1.1 安裝 1.1.1 版本 1.1.2 安裝 1.1.3 連接 1.2 數據模型 1.3 SQL簡介 1.3.1 分類 1.3.2 SQL通用語法 2.DDL 2.1 數據庫操作 2.2 圖形化工具 2.2.1 使用 2.3 表操作 2.3.1 創建表 2.3.1.1約束 2.3.1.2 數據類型 2.3.1.3 案例 2.3.2 DDL&am…