EF簡介
ORM的概念
對象關系映射Object Relation Mapping ,通俗說:用操作對象的方式來操作數據庫。是一種程序技術,用於實現面向對象編程語言里不同類型關系數據之間的轉換,從效果上說,它其實是創造了一個可在編程語言中使用的“虛擬對象數據庫”
關於使用服務端語言操作數據庫-ADO.NET技術,ADO.NET技術學習程序分層時學習過Model層,而這里的模型層指的是在服務端編程語言中用來映射數據庫中數據模型的一個對象映射。
而在ORM技術而言,可以理解為ORM主要是為了更方便快速的實現ADO.NET技術
ORM技術的優勢
- 首先在學習編程中,最終都要學習的是訪問數據庫,而在C#語言中使用C#語言訪問數據庫技術是微軟提供的ADO.NET技術
- 因此在做程序編程時,只要有關數據庫的操作,我們總結出來一套經驗:先寫DBHelper,然后創建目標數據庫中的數據對象模型,這個步驟很麻煩,但是又不得不寫
- 實現更加方便快捷的開發,方便數據庫移植
.NET中的ORM框架
- NHibernate
- MyBatis.NET
- LinQ to SQL(已經不使用)
- ADO.NET Entity Framework
EF的本質
EF底層仍然是對ADO.Net的封裝。EF支持SQLServer、MYSQL、Oracle、Sqlite等所有主流數據庫。
Object Services
它是Entity Framework提供的一系列操作業務對象的API。這些API都依賴Entity Client實現對數據庫的訪問
EDM實體數據模型
- 作用:將關系數據庫模型映射為實體數據模型,由三部分組成,存放在一個擴展名為.edmx的XML文件中
- SSDL:負責與數據庫中的數據表做實體對應(就是將數據庫中數據表結構和關系用XML文件描述)
- MSL:將存儲模型中的字段和概念模型中的屬性對應
- CSDL:概念模型對應的實體類,用實體類表示數據庫中的對象
Entity Client實體代理
- 概念:Entity Framework實現了一套類似於ADO.NET中的數據庫操作類,這些操作類稱之為Entity Client
- 作用:用來操作EMD實體數據模型
ADO.NET Provider
- 作用:翻譯成SQL語句,用來訪問數據庫
- 說明:Entity Framework是ADO.NET的一個技術子集
Entity Client和ADO.NET
- ADO.NET的連接類是向數據庫發送SQL命令操作表或試圖,Entity Client是向EDM發送Entity SQL
- Entity Client通過Entity Connection、Entity Command等類進行模擬ADO.NET,有自己的SQL語句
- Entity Client將查詢轉交給數據庫提供者ADO.NET Provider,並由數據庫提供者翻譯為SQL語句
EF應用程序有以下優點
- 應用程序可以通過更加以應用程序為中心的概念性模型(包括具有繼承性、復雜成員和關系的類型)來工作。
- 應用程序不再對特定的數據引擎或存儲架構具有硬編碼依賴性。
- 可以在不更改應用程序代碼的情況下更改概念性模型與特定於存儲的架構之間的映射。
- 開發人員可以使用可映射到各種存儲架構(可能在不同的數據庫管理系統中實現)的一致的應用程序對象模型。
- 多個概念性模型可以映射到同一個存儲架構。
- 語言集成查詢支持可為查詢提供針對概念性模型的編譯時語法驗證。
EF框架的搭建
EF的創建
使用EF進行數據庫開發的時候有兩個東西建:建數據庫(T_Persons),建模型類(Person)。EF的三種創建方法:
- DataBase First(數據庫優先):先創建數據庫表,然后自動生成EDM文件,EDM文件生成模型類。簡單展示一下DataBase First 的使用。
- Model First(模型優先):先創建Edm文件,Edm文件自動生成模型類和數據庫;
- Code First(代碼優先):程序員自己寫模型類,然后自動生成數據庫。沒有Edm。
三種創建的區別
- DataBase First 簡單、方便,但是當項目大了之后會非常痛苦;
- Code First 入門門檻高,但是適合於大項目。
- Model First…… (不需要考慮)
無論哪種First,一旦創建好了數據庫、模型類之后,后面的用法都是一樣的。業界都是推薦使用Code First,新版的EF中只支持Code First,因此我們這里只講Code First。
DataBase First
- 首先在數據庫中創建好數據庫、數據表,以及表結構
- 在創建C#項目時,添加EF框架,選擇“ADO.NET 實體數據模型”
- 在實體數據模型向導中選擇“來自數據庫的EF設計器”
- 進行數據庫連接中“建立新的連接”
- 進行尋找連接目標數據庫,創建EF數據實體模型
- App.config:配置文件,里面有連接數據庫字符串,EF的相關配置
- StudentModel.edmx:EDM元數據文件
- StudentModel.Context.cs:數據庫上下文類,可以理解為是映射關系類
- StudentMode.tt:實體類集合
EDM元數據
EDM設計器模式和XML結構
XML結構中明顯有三個類型節點,分別對應EDM中的存儲模型、概念模型、映射
實體文件
在StudentMode.tt文件里面,可以找到實體文件和選擇的數據庫表的對應實體表
數據庫上下文類
namespace DBFirst { using System; using System.Data.Entity; using System.Data.Entity.Infrastructure;
public partial class StudentManagerEntities : DbContext { public StudentManagerEntities() : base("name=StudentManagerEntities") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { throw new UnintentionalCodeFirstException(); } public virtual DbSet<Admin> Admin { get; set; } public virtual DbSet<Course> Course { get; set; } public virtual DbSet<Score> Score { get; set; } public virtual DbSet<Student> Student { get; set; } }
}
StudentModel.Context.cs集成自DbContext
DbContext-實體對象容器
作用:操作數據庫的工具,負責管理對象的CRUD(增、刪、改、查)操作,以及相應的事務及並發問題
特別注意:某個數據表的字段全部都是外鍵的時候,不會生成該表對應的實體類
使用EF查詢單表數據
在DbSet< T>對象中查詢符合條件的實體,一般用基類IEnumerable< Student>類型包含的兩個方法
IQueryable<Student> Where<Student>(Expression<Func<Student,bool>> predicate)
Student SingleOrDefault<Student>(Expression<Func<Student,bool>> predicate)
private void Form1_Load(object sender, EventArgs e)
{
StudentManagerEntities studentEF = new StudentManagerEntities();
List<Student> list = studentEF.Student.ToList();
}
使用EF實現CRUD
-
添加數據
使用DbSet< T>中的Add方法
然后使用DbContext的SaveChanges()方法
Student stu = new Student() { SName=txtName.Text.Trim(), SAge=int.Parse(txtAge.Text.Trim()),SEmail=txtEmail.Text.Trim(), SSex=radioButton1.Checked?"男":"女" }; studentEF.Student.Add(stu);//只是將實體對象添加到了數據庫上下文對應的對象集合中,而並非添加到了數據庫中了 int res = studentEF.SaveChanges();//將數據庫上下文中的更改保存到數據庫中
-
修改數據
從DbContext中獲取實體
修改數據
使用DbContext的SavaChanges()方法
if (radioButton1.Checked) { currentStu.SSex = "男"; } else if (radioButton2.Checked) { currentStu.SSex = "女"; } currentStu.SName = txtName.Text.Trim(); currentStu.SAge = int.Parse(txtAge.Text.Trim()); currentStu.SEmail = txtEmail.Text.Trim(); int res = entities.SaveChanges(); this.Close();
-
使用EF刪除
使用DbContext獲取實體
使用DbSet< T>的Remove()方法
使用DbContext的SaveChanges()方法
Student stu = studentEF.Student.Find(int.Parse(dataGridView1.SelectedRows[0].Cells["Id"].Value.ToString())); if (stu!=null) { studentEF.Student.Remove(stu); studentEF.SaveChanges(); RefreshStudent(); }
Code First
Code First的微軟的推薦用法是程序員只寫模型類,數據庫由EF 幫我們生成,當修改模型類之后,EF 使用“DB Migration”自動幫我們更改數據庫。但是這種做法太激進,不適合很多大項目的開發流程和優化,只適合於項目的初始開發階段。Java的Hibernate 中也有類似的DDL To SQL 技術,但是也是用的較少。“DB Migration”也不利於理解EF,因此在初學階段,我們將會禁用“DB Migration”,采用更實際的“手動建數據庫和模型類”的方式。