推薦關注「碼俠江湖」加星標,時刻不忘江湖事
掌握 ORM 開發方式是每一個 .NET 開發者所必備的技能,而且 .NET 平臺有很多優秀的 ORM 框架。
很多人都會詬病 .NET 官方標配的 Entity Framework,感覺其笨重難用、性能低下。
但其實經過多年發展,EF Core 已經是 .NET 平臺中的新一代 ORM 框架。
雖然是上一代 EF 的跨平臺版本,但在其本就無比安全穩定的基礎上,做了很多的改進,摒棄了一些包袱、優化了性能,豐富了擴展等。
這個系列的目的,就是全面的講述 EF Core,讓大家對其有一個系統的了解,內容較為精煉,不會有太多廢話。
基礎概念
想要使用 EF Core,必須安裝 Microsoft.EntityFrameworkCore
庫,它提供了 EF Core 核心功能。
除此之外,我們還需要安裝與你使用的數據庫相匹配的數據庫提供程序。
比如,本文示例使用的是 SQL Server LocalDB
,所以我需要安裝 Microsoft.EntityFrameworkCore.SqlServer
庫。
模型
EF Core 是一個 ORM 框架。
什么是 ORM?也就是 「Object Relational Mapping」,對象關系映射。
這里的 Object ,在 EF Core 中,以實體類來表示。
實體類是 EF Core 用于映射到數據庫表的一個類。
在這個示例中,有一個 Entities
文件夾,用來存放與 EF Core 相關的實體類,里面有一個名為 Account
的實體類。
EF Core 中有一系列的規則,來幫助它將實體類映射到數據庫表中。
以 Account
實體類為例,這個映射過程很簡單:
首先,EF Core 通過實體類,擁有了用于列和配置映射的表的信息。
接下來,這個類中的所有公共屬性,都會被映射到表的列中,并具有與屬性相同的名稱。
最后,EF Core 使用命名約定,在數據庫表中從 AccountId
屬性中,創建一個主鍵。
連接字符串
EF Core 是一個面向數據庫的 ORM 框架,我們就必須為它提供數據庫的信息,也就是數據庫連接字符串。
一般情況下,我們使用 「appsettings.json」 配置文件,為 EF Core 提供連接字符串。
{"ConnectionStrings":?{"DefaultConnection":?"Server=(localdb)\\MSSQLLocalDB;Database=CodeMan;Trusted_Connection=True;MultipleActiveResultSets=true"}
}
在這個示例中,提供的連接字符串是,SQL Server LocalDB 中的默認實例,指定的數據庫名稱是 「CodeMan」。
需要注意的是,由于連接字符串屬于敏感信息,所以使用配置文件來存儲連接字符串,并不是最好的做法,特別是對于生產環境。
那么針對生產環境,更好的方法就是使用環境變量來提供諸如連接字符串的敏感信息。
依賴注入
EF Core 中有一個非常重要的東西,就是數據上下文類。
在這個示例中,Entities
目錄中的 ApplicationContext
類型,就是 EF Core 在當前應用中的上下文類。
這個類必須繼承自 DbContext
基類,它包含訪問數據庫的信息和配置。
構造函數使用 DbContextOptions
參數,為基類提供額外的選項。
其中最重要的是 DbSet<Account>
類型的 Accounts
屬性。
EF Core 會在上下文類中,查找所有的公共 DbSet
屬性,將它們的名稱映射到數據庫中的表的名稱。
然后,它會進入 DbSet<T>
提供的泛型類,在我們的例子中,它是一個 Account
類,并將所有的公共屬性,映射到表中具有相同名稱和類型的列。
如果 Account
類對其他類有任何引用,EF Core 還會使用這些引用屬性,并在數據庫中創建相應的關系。
讓我們回到在?Main
?方法中:
首先,我們創建了一個讀取?appsettings.json?配置文件的配置對象,用來獲取連接字符串
然后,在依賴注入系統中,通過使用?AddDbContext
?方法,來注冊?ApplicationContext
?上下文類
在它的配置委托中,使用?UseSqlServer
?方法,設置連接字符串。
在這個示例中,還注冊了一個?AccountService
?服務,該服務的實現類,通過構造函數注入了上下文實例。
這樣我們就可以在服務類中,使用上下文實例。
上下文池
需要注意的是,在EF Core 中,注冊上下文類的方法有兩種:
AddDbContext
方法注冊的上下文類型,生命周期模式默認是作用域,這個作用域的范圍是線程,在 ASP.NET Core 應用中作用域的范圍表現為一個請求。
因為上下文實例是非線程安全的,所以我們一般不需要去修改它的生命周期模式。
另外還有一個 AddDbContextPool
方法,它用來配置上下文實例池。
上下文池可以重復使用上下文實例,而不是為每個請求創建新的實例。
當應用請求上下文實例時 EF Core 會首先檢查池中,是否有可用的實例。
請求處理完成后,上下文實例的任何狀態都會被重置,然后回到池中。
也就是說,保存在池中的可以復用的上下文實例,它不會再被初始化。所以,它不太適合在每一次使用它,都需要初始化的場景。
上下文池可以提高大型 Web 應用的吞吐量。默認情況下,池中保持的上下文實例數是 1024 個,這個值可以通過 poolSize
參數進行修改,示例中修改為 2048 個。
一旦池中保存的實例數超出池大小,就不會再保存新的上下文實例,此時 EF Core 會回退到「按需創建實例的非池行為」。
池的大小需要根據實際情況去設置,池容量太小,如果不夠用就會回退到非池行為,此時池的意義不大。
如果池容量太大,則可能消耗不必要的內存,因為未使用的上下文實例,也保留在池中。
一般情況下,池的性能提升通常可以忽略不計,除非是在高度優化的方案中。
上下文類
我們現在再回頭看一看 ApplicationContext
上下文類:
它的構造函數中,接受了一個 DbContextOptions
類型的參數,這個參數用來提供上下文的選項。
除了直接使用 DbContextOptions
類型,還可以使用泛型版本 DbContextOptions
類型。
public?ApplicationContext(DbContextOptions<ApplicationContext>?options)
無論使用哪個版本,我們的應用都會正常工作。
使用哪一個版本,取決于你的應用中是否有多種上下文類型。
如果應用中有多種上下文類型,就推薦使用泛型版本,而當前示例的情況并非如此,所以使用的是非泛型版本。
DbContext
有三個重要的屬性:
Database 屬性負責與數據庫的交互、數據庫的遷移/創建和原始 SQL 查詢。
ChangeTracker
屬性用于跟蹤通過同一上下文實例,查詢出的實體狀態。Model
屬性提供了對 EF Core 在連接,或創建數據庫時,使用的數據庫模型。
我們可以使用 Model
屬性,來訪問每個實體及其屬性的信息。
不過,這需要我們安裝 Microsoft.EntityFrameworkCore.Relationa
庫。
然后在 AccountService
實現類的 Run 方法中,就可以通過使用上下文實例的 Model
屬性,找到上下文中的任意實體,并獲取它的一些信息,比如表名和主鍵字段名。
小結
這篇文章,講述了 EF Core 的一些基本概念:模型、連接字符串、依賴注冊、上下文池與上下文類。
下篇文章,我們將盤點一下 EF Core 的屬性配置。
更多精彩內容,請關注我▼▼
如果喜歡我的文章,那么
在看和轉發是對我最大的支持!
(戳下面藍字閱讀)
ASP.NET 6 中間件系列
推薦關注微信公眾號:碼俠江湖
? ? ? ? ? ? ? ? ? ? ? ??覺得不錯,點個在看再走喲
如果喜歡我的文章,那么
在看和轉發是對我最大的支持!
(戳下面藍字閱讀)
ASP.NET 6 中間件系列
推薦關注微信公眾號:碼俠江湖
? ? ? ? ? ? ? ? ? ? ? ??覺得不錯,點個在看再走喲