C# 數據庫訪問與ORM框架全面指南:從ADO.NET到Entity Framework Core

在現代應用開發中,數據持久化是核心需求之一。作為.NET生態系統中的主力語言,C#提供了豐富多樣的數據庫訪問技術和工具。本文將全面探討C#中的數據庫訪問方式,重點介紹三種主流ORM(對象關系映射)框架:Entity Framework Core、Dapper和NHibernate,幫助開發者根據項目需求做出合理的技術選型。

第一部分:基礎數據庫訪問 - ADO.NET

1.1 ADO.NET架構概述

ADO.NET是.NET平臺數據訪問的基石,提供了一套面向連接的、斷開式的數據訪問模型。其主要組件包括:

  • Connection:建立與數據庫的連接

  • Command:執行SQL命令

  • DataReader:高效的前向只讀數據流

  • DataAdapter:在數據源和DataSet之間架橋

  • DataSet:內存中的數據庫表示

1.2 典型使用模式

// 連接字符串示例
string connStr = "Server=.;Database=Northwind;Integrated Security=True;";using (SqlConnection conn = new SqlConnection(connStr))
{// 打開連接conn.Open();// 執行查詢string sql = "SELECT ProductID, ProductName FROM Products WHERE CategoryID = @CategoryID";using (SqlCommand cmd = new SqlCommand(sql, conn)){cmd.Parameters.AddWithValue("@CategoryID", 1);using (SqlDataReader reader = cmd.ExecuteReader()){while (reader.Read()){Console.WriteLine($"{reader["ProductID"]}: {reader["ProductName"]}");}}}// 執行插入string insertSql = "INSERT INTO Products (ProductName, CategoryID) VALUES (@Name, @CatID)";using (SqlCommand cmd = new SqlCommand(insertSql, conn)){cmd.Parameters.AddWithValue("@Name", "New Product");cmd.Parameters.AddWithValue("@CatID", 1);int rowsAffected = cmd.ExecuteNonQuery();Console.WriteLine($"插入了 {rowsAffected} 行");}
}

1.3 ADO.NET優缺點分析

優點

  • 最接近數據庫底層的訪問方式

  • 性能最佳

  • 完全控制SQL語句

  • 適合復雜查詢和存儲過程調用

缺點

  • 需要手動編寫大量樣板代碼

  • 容易產生SQL注入漏洞

  • 對象關系映射需要手動實現

  • 維護成本高

第二部分:現代ORM框架

2.1 Entity Framework Core

2.1.1 EF Core概述

Entity Framework Core是微軟官方推出的ORM框架,是.NET生態中最流行的數據訪問解決方案。

2.1.2 核心概念

  • DbContext:數據庫會話,工作單元模式的實現

  • DbSet:實體集合,對應數據庫表

  • 遷移(Migrations):代碼優先的數據庫架構管理

  • LINQ提供程序:將LINQ轉換為SQL

2.1.3 完整示例

// 定義實體
public class Blog
{public int BlogId { get; set; }public string Url { get; set; }public int Rating { get; set; }public List<Post> Posts { get; set; }
}public class Post
{public int PostId { get; set; }public string Title { get; set; }public string Content { get; set; }public int BlogId { get; set; }public Blog Blog { get; set; }
}// 定義DbContext
public class BloggingContext : DbContext
{public DbSet<Blog> Blogs { get; set; }public DbSet<Post> Posts { get; set; }protected override void OnConfiguring(DbContextOptionsBuilder options)=> options.UseSqlServer("Server=.;Database=BloggingDemo;Trusted_Connection=True;");
}// 使用示例
using (var db = new BloggingContext())
{// 創建var blog = new Blog { Url = "http://example.com", Rating = 5 };db.Blogs.Add(blog);db.SaveChanges();// 查詢var topBlogs = db.Blogs.Where(b => b.Rating > 3).OrderByDescending(b => b.Rating).ToList();// 更新var firstBlog = db.Blogs.First();firstBlog.Url = "http://updated.com";db.SaveChanges();// 刪除var lastBlog = db.Blogs.OrderBy(b => b.BlogId).Last();db.Blogs.Remove(lastBlog);db.SaveChanges();
}

2.1.4 EF Core高級特性

  • 延遲加載virtual導航屬性+代理

  • 預先加載Include/ThenInclude

  • 顯式加載Entry(...).Collection(...).Load()

  • 全局查詢過濾器modelBuilder.Entity<T>().HasQueryFilter(...)

  • 影子屬性:模型中未定義的列

  • 值轉換器:自定義類型映射

2.2 Dapper

2.2.1 Dapper概述

Dapper是Stack Overflow開發的高性能微型ORM,在ADO.NET基礎上提供了簡單的對象映射功能。

2.2.2 核心特點

  • 輕量級(單個文件)

  • 幾乎零學習成本

  • 性能接近原生ADO.NET

  • 支持多映射和存儲過程

2.2.3 完整示例

using Dapper;
using System.Data.SqlClient;// 基本查詢
string connectionString = "Server=.;Database=Northwind;Integrated Security=True;";using (var connection = new SqlConnection(connectionString))
{var products = connection.Query<Product>("SELECT * FROM Products WHERE CategoryID = @CatID",new { CatID = 1 });foreach (var product in products){Console.WriteLine(product.ProductName);}
}// 多映射示例
var sql = @"SELECT p.*, c.* FROM Products p INNER JOIN Categories c ON p.CategoryID = c.CategoryIDWHERE p.ProductID = @Id";using (var connection = new SqlConnection(connectionString))
{var product = connection.Query<Product, Category, Product>(sql,(prod, cat) => { prod.Category = cat; return prod; },new { Id = 1 },splitOn: "CategoryID").FirstOrDefault();Console.WriteLine($"{product.ProductName} 屬于 {product.Category.CategoryName}");
}// 執行存儲過程
using (var connection = new SqlConnection(connectionString))
{var parameters = new DynamicParameters();parameters.Add("@CategoryID", 1);parameters.Add("@ProductCount", dbType: DbType.Int32, direction: ParameterDirection.Output);var products = connection.Query<Product>("CustOrderHist",parameters,commandType: CommandType.StoredProcedure);int productCount = parameters.Get<int>("@ProductCount");
}

2.3 NHibernate

2.3.1 NHibernate概述

NHibernate是.NET平臺上的成熟ORM框架,移植自Java的Hibernate,功能全面但配置復雜。

2.3.2 核心概念

  • SessionFactory:線程安全,應用生命周期單例

  • Session:工作單元,非線程安全

  • 映射文件:.hbm.xml或Fluent配置

  • HQL:Hibernate查詢語言

  • Criteria API:類型安全的查詢構建

2.3.3 完整示例

<!-- Product.hbm.xml -->
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"><class name="Product" table="Products"><id name="Id" column="ProductID"><generator class="identity" /></id><property name="Name" column="ProductName" /><property name="Price" /><many-to-one name="Category" column="CategoryID" /></class>
</hibernate-mapping>
// 配置和用法
var cfg = new Configuration();
cfg.Configure(); // 讀取hibernate.cfg.xml
cfg.AddAssembly(typeof(Product).Assembly);var sessionFactory = cfg.BuildSessionFactory();using (var session = sessionFactory.OpenSession())
using (var tx = session.BeginTransaction())
{// 保存var newProduct = new Product { Name = "New Product", Price = 9.99m,Category = session.Load<Category>(1)};session.Save(newProduct);// 查詢var products = session.CreateCriteria<Product>().Add(Restrictions.Like("Name", "N%")).List<Product>();// HQL查詢var hqlProducts = session.CreateQuery("FROM Product WHERE Price > :price").SetDecimal("price", 5m).List<Product>();tx.Commit();
}

第三部分:技術選型指南

3.1 比較矩陣

特性ADO.NETDapperEF CoreNHibernate
學習曲線
性能最高
開發速度
功能豐富度最高
LINQ支持有限完整部分
遷移工具
社區支持最高

3.2 推薦場景

選擇ADO.NET當

  • 需要極致性能

  • 項目簡單,表結構穩定

  • 需要完全控制SQL

  • 使用復雜存儲過程

選擇Dapper當

  • 需要接近原生性能

  • 項目使用微服務架構

  • 已有良好設計的SQL

  • 需要輕量級解決方案

選擇EF Core當

  • 開發速度是關鍵因素

  • 使用代碼優先開發

  • 需要LINQ支持

  • 項目中等復雜度

選擇NHibernate當

  • 需要最豐富的ORM功能

  • 項目非常復雜

  • 需要二級緩存等高級特性

  • 團隊有Hibernate經驗

第四部分:最佳實踐與性能優化

4.1 通用最佳實踐

  1. 連接管理:始終確保連接被正確關閉(使用using語句)

  2. 參數化查詢:永遠使用參數防止SQL注入

  3. 錯誤處理:實現適當的重試機制

  4. 日志記錄:記錄關鍵數據庫操作

  5. 分頁處理:大數據集必須分頁

4.2 EF Core特定優化

  1. 批量操作

    // 不好的做法
    foreach (var item in items)
    {context.Add(item);context.SaveChanges(); // 每次保存
    }// 好的做法
    context.AddRange(items);
    context.SaveChanges(); // 批量保存
  2. 選擇合適的數據加載方式

    // 預先加載(查詢時)
    var blogs = context.Blogs.Include(b => b.Posts).ToList();// 顯式加載(需要時)
    var blog = context.Blogs.First();
    context.Entry(blog).Collection(b => b.Posts).Load();// 延遲加載(訪問時,需配置)
    public class Blog
    {public virtual ICollection<Post> Posts { get; set; }
    }
  3. 禁用跟蹤

    var blogs = context.Blogs.AsNoTracking() // 只讀操作使用.ToList();
  4. 使用原始SQL優化復雜查詢

    var blogs = context.Blogs.FromSqlRaw("SELECT * FROM Blogs WHERE Rating > {0}", 3).ToList();

4.3 Dapper優化技巧

  1. 使用多映射減少查詢次數

    var sql = @"SELECT * FROM Orders o INNER JOIN Customers c ON o.CustomerID = c.CustomerIDWHERE o.OrderDate > @Date";var orders = connection.Query<Order, Customer, Order>(sql,(order, customer) => { order.Customer = customer; return order; },new { Date = DateTime.Now.AddDays(-30) },splitOn: "CustomerID");
  2. 批量插入

    var sql = "INSERT INTO Products (Name, Price) VALUES (@Name, @Price)";
    connection.Execute(sql, products); // products是對象列表

結語

C#生態系統提供了從底層到高層的完整數據庫訪問解決方案。對于大多數應用場景,Entity Framework Core提供了最佳的生產力和功能平衡;對性能敏感的場景,Dapper是不二之選;而復雜的企業級應用可能會從NHibernate的豐富功能中受益。無論選擇哪種技術,理解底層原理和遵循最佳實踐都是構建高效、可維護數據訪問層的關鍵。

希望這篇全面指南能幫助您在C#項目中做出明智的數據庫訪問技術決策。根據項目需求、團隊技能和性能要求選擇最適合的工具,并記住:沒有放之四海而皆準的解決方案,只有最適合特定場景的選擇。

?

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

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

相關文章

day19 leetcode-hot100-37(二叉樹2)

104. 二叉樹的最大深度 - 力扣&#xff08;LeetCode&#xff09; 1.深度優先遍歷&#xff08;遞歸&#xff09;ps:不好理解&#xff0c;所以我一般不喜歡用遞歸 思路 典型算法&#xff0c;用遞歸求出高度&#xff0c;每次都是深度優先。 具體算法 /*** Definition for a bi…

【LLMs篇】13:LLaDA—大型語言擴散模型

欄目內容論文標題大型語言擴散模型 (Large Language Diffusion Models)核心思想提出LLaDA&#xff0c;一種基于擴散模型的LLM&#xff0c;通過前向掩碼和反向預測過程建模語言分布&#xff0c;挑戰自回歸模型&#xff08;ARM&#xff09;在LLM領域的主導地位&#xff0c;并展示…

Deepfashion2 數據集使用筆記

目錄 數據類別: 篩選類別數據: 驗證篩選前2個類別: Deepfashion2 的解壓碼 數據類別: 類別含義: Class idx類別名稱英文名稱0短上衣short sleeve top1長上衣long sleeve top2短外套short sleeve outwear3長外套long sleeve outwear4裙子skirt5褲子trousers6連衣裙dre…

Java并發編程哲學系列匯總

文章目錄 并發編程基礎并發編程進階并發編程實踐 并發編程基礎 Java并發編程基礎小結 Java線程池知識點小結 詳解JUC包下各種鎖的使用 并發編程利器Java CAS原子類全解 深入理解Java中的final關鍵字 Java并發容器深入解析&#xff1a;HashMap與ArrayList線程安全問題及解…

git 之 stash

一、git stash&#xff1a;臨時保存工作區修改 作用 將當前工作目錄和暫存區的未提交修改保存到棧中&#xff0c;并恢復工作區到上一次提交的干凈狀態。 適用場景&#xff1a; 臨時切換分支修復緊急 Bug拉取遠程代碼前清理工作區保存實驗性代碼避免生成無效提交 常用命令&am…

vxe-grid 雙擊行,打開expand的內容

1、官網api Vxe Table v4.6&#xff08;根據版本&#xff09; 要調用這個事件&#xff0c;雙擊單元格&#xff0c;我們打開type"expand"的內容 2、打開的事件toggleRowExpand 3、事件的說明 這個方法&#xff0c;會自動判斷當前展開的狀態&#xff0c;然后去觸發相…

Java Stream 高級實戰:并行流、自定義收集器與性能優化

一、并行流深度實戰&#xff1a;大規模數據處理的性能突破 1.1 并行流的核心應用場景 在電商用戶行為分析場景中&#xff0c;需要對百萬級用戶日志數據進行實時統計。例如&#xff0c;計算某時段內活躍用戶數&#xff08;訪問次數≥3次的用戶&#xff09;&#xff0c;傳統循環…

計算機系統結構-第5章-監聽式協議

監聽式協議******&#xff1a; 思想: 每個Cache除了包含物理存儲器中塊的數據拷貝之外&#xff0c;也保存著各個塊的共享狀態信息。 Cache通常連在共享存儲器的總線上&#xff0c;當某個Cache需要訪問存儲器時&#xff0c;它會把請求放到總線上廣播出去&#xff0c;其他各個C…

(c++)string的模擬實現

目錄 1.構造函數 2.析構函數 3.擴容 1.reserve(擴容不初始化) 2.resize(擴容加初始化) 4.push_back 5.append 6. 運算符重載 1.一個字符 2.一個字符串 7 []運算符重載 8.find 1.找一個字符 2.找一個字符串 9.insert 1.插入一個字符 2.插入一個字符串 9.erase 10…

學習筆記(24): 機器學習之數據預處理Pandas和轉換成張量格式[2]

學習筆記(24): 機器學習之數據預處理Pandas和轉換成張量格式[2] 學習機器學習&#xff0c;需要學習如何預處理原始數據&#xff0c;這里用到pandas&#xff0c;將原始數據轉換為張量格式的數據。 學習筆記(23): 機器學習之數據預處理Pandas和轉換成張量格式[1]-CSDN博客 下面…

LeetCode 2297. 跳躍游戲 VIII(中等)

題目描述 給定一個長度為 n 的下標從 0 開始的整數數組 nums。初始位置為下標 0。當 i < j 時&#xff0c;你可以從下標 i 跳轉到下標 j: 對于在 i < k < j 范圍內的所有下標 k 有 nums[i] < nums[j] 和 nums[k] < nums[i] , 或者對于在 i < k < j 范圍…

【前端】緩存相關

本知識頁參考&#xff1a;https://zhuanlan.zhihu.com/p/586060532 1. 概述 1.1 應用場景 靜態資源 場景&#xff1a;圖片、CSS、JS 文件等靜態資源實現&#xff1a;使用 HTTP 緩存控制頭&#xff0c;或者利用 CDN 進行邊緣緩存 數據緩存 場景&#xff1a;請求的返回結果實現…

獵板硬金鍍層厚度:高頻通信領域的性能分水嶺

在 5G 基站、毫米波雷達等高頻場景中&#xff0c;硬金鍍層厚度的選擇直接決定了 PCB 的信號完整性與長期可靠性。獵板硬金工藝&#xff1a; 1.8μm 金層搭配羅杰斯 4350B 基材的解決方案&#xff0c;在 10GHz 頻段實現插入損耗&#xff1c;0.15dB/cm&#xff0c;較常規工藝降低…

第35次CCF計算機軟件能力認證-5-木板切割

原題鏈接&#xff1a; TUOJ 我自己寫的35分正確但嚴重超時的代碼 #include <bits/stdc.h> using namespace std; int main() {int n, m, k;cin >> n >> m >> k;vector<unordered_map<int, int>> mp(2);int y;for (int i 1; i < n; …

【藍橋杯】包子湊數

包子湊數 題目描述 小明幾乎每天早晨都會在一家包子鋪吃早餐。他發現這家包子鋪有 NN 種蒸籠&#xff0c;其中第 ii 種蒸籠恰好能放 AiAi? 個包子。每種蒸籠都有非常多籠&#xff0c;可以認為是無限籠。 每當有顧客想買 XX 個包子&#xff0c;賣包子的大叔就會迅速選出若干…

pikachu通關教程-目錄遍歷漏洞(../../)

目錄遍歷漏洞也可以叫做信息泄露漏洞、非授權文件包含漏洞等. 原理:目錄遍歷漏洞的原理比較簡單&#xff0c;就是程序在實現上沒有充分過濾用戶輸入的../之類的目錄跳轉符&#xff0c;導致惡意用戶可以通過提交目錄跳轉來遍歷服務器上的任意文件。 這里的目錄跳轉符可以是../…

[概率論基本概念4]什么是無偏估計

關鍵詞&#xff1a;Unbiased Estimation 一、說明 對于無偏和有偏估計&#xff0c;需要了解其敘事背景&#xff0c;是指整體和抽樣的關系&#xff0c;也就是說整體的敘事是從理論角度的&#xff0c;而估計器原理是從實踐角度說事&#xff1b;為了表明概率理論&#xff08;不可…

面試題——計算機網絡:HTTP和HTTPS的區別?

HTTP&#xff08;HyperText Transfer Protocol&#xff09;&#xff1a;作為互聯網上應用最廣泛的網絡通信協議&#xff0c;HTTP是基于TCP/IP協議族的應用層協議。它采用標準的請求-響應模式進行通信&#xff0c;通過簡潔的報文格式&#xff08;包含請求行、請求頭、請求體等&a…

uni-app學習筆記十九--pages.json全局樣式globalStyle設置

pages.json 頁面路由 pages.json 文件用來對 uni-app 進行全局配置&#xff0c;決定頁面文件的路徑、窗口樣式、原生的導航欄、底部的原生tabbar 等。 導航欄高度為 44px (不含狀態欄)&#xff0c;tabBar 高度為 50px (不含安全區)。 它類似微信小程序中app.json的頁面管理部…

SQL思路解析:窗口滑動的應用

目錄 &#x1f3af; 問題目標 第一步&#xff1a;從數據中我們能直接得到什么&#xff1f; 第二步&#xff1a;我們想要的“7天窗口”長什么樣&#xff1f; 第三步&#xff1a;SQL 怎么表達“某一天的前六天”&#xff1f; &#x1f50d;JOIN 比窗口函數更靈活 第四步&am…