在DbFirst模式中,咱們添加一個EDM(Entity Data Model)後會自動生成一個.edmx文件,這個文件中包含一個繼承DbContext類的上下文實例,DbContext是實體類和數據庫之間的橋樑,DbContext主要負責與數據交互,主要做用:html
一、DbContext包含全部的實體映射到數據庫表的實體集(DbSet < TEntity >)。sql
二、DbContext 將LINQ-to-Entities查詢轉換爲SQL查詢並將其發送到數據庫。數據庫
三、更改跟蹤: 它跟蹤每一個實體從數據庫中查詢出來後發生的修改變化。post
四、持久化數據: 它也基於實體狀態執行插入、更新和刪除操做到數據庫中。spa
從上圖能夠看出:在EF工做過程當中,對實體的操做會致使實體狀態的變化,Context根據實體狀態的變化生成和執行對應的SQL語句。簡言之,對實體的操做給實體添加標籤(如Added,Deleted,Modified),DbContext根據實體的標籤生成(Insert,Delete,Update)Sql語句,而後EF經過Ado.Net執行Sql實現持久化。.net
DbSet 表示上下文中給定類型的全部實體的集合或可從數據庫中查詢的給定類型的全部實體的集合。 可使用 DbContext.Set 方法從 DbContext 中建立 DbSet 對象,DbSet對應着數據庫中的表,DbSet經常使用的方法以下3d
Add(Entity)/AddRange | 返回添加的Entity | 添加實體到context中,並給實體標記Added狀態 dbcontext.Students.Add(studentEntity) |
AsNoTracking<Entity> | DBQuery<Entity> | 獲取一個不被context緩衝和追蹤的序列,多用於獲取只讀序列 var studentList = dbcontext.Students.AsNoTracking<Student>().ToList<Student>(); |
Attach(Entity) | 返回添加的Entity | 將實體添加到context上下文中 dbcontext.Students.Attach(studentEntity); |
Find(int) | 返回對應Id的Entity | 經過主鍵獲取實體對象,若是在數據庫和context中不存在那麼返回null,注:也會返回在context中存在但尚未寫入數據庫的實體對象。 Student studEntity = dbcontext.Students.Find(1); |
Include | DBQuery | include必須是外鍵鏈接,且當即執行;join鏈接不須要外鍵 ,延時執行 var studentList = dbcontext.Students.Include("StudentAddress").ToList<Student>(); var studentList = dbcontext.Students.Include(s => s.StudentAddress).ToList<Student>(); |
Remove/RemoveRange | 返回刪除的entity | 刪除實例,並給實例對象添加deleted標記。 dbcontext.Students.Remove(studentEntity); |
SqlQuery | DBSqlQuery | 經過sql獲取實例集合. 默認狀況下,返回的集合被追蹤的,可使用AsNoTracking()取消追蹤。 var studentEntity = dbcontext.Students.SqlQuery("select * from student where studentid = 1").FirstOrDefault<Student>(); |
在EF中實體的五種狀態:code
一、detached:實體不在上下文的追蹤範圍內。如剛new的實例處於detached,能夠經過Attach()添加到上下文,此時的狀態是unchanged。htm
二、unchanged:未改變,如剛從數據庫讀出來的實例對象
三、added:添加狀態 通常執行 db.Set<T>.Add(t)/ AddRange(ts)時標記爲added。由於新對象在數據庫中沒有相應的記錄,全部不能轉成deleted和modified狀態。
四、deleted:刪除狀態 通常執行 db.Set<T>.Remove(t)/ RemoveRange(ts)時標記爲deleted。數據庫中必須先有了相應的記錄,全部deleted不能轉爲added狀態。
五、modified:修改狀態 改變了實體的屬性處於這個狀態,能夠轉爲deleted,不能轉爲added狀態。
當EF從數據庫中提取一條記錄生成一個實體對象以後,應用程序能夠針對它的操做太多了,EF是怎麼知道哪一個對象處於哪一個狀態的?
EF的解決方案是:爲當前全部須要跟蹤的實體對象,建立一個相應的DbEntityEntry對象,此對象包容着實體對象每一個屬性的三個值:Current Value、Original Value和Database Value,只要比較這三個值,很容易地就知道哪一個屬性值被修改了(設置:context.Configuration.AutoDetectChangesEnabled = false則不會去追蹤,默認是打開的),從而生成相應的Sql命令。對象的狀態會隨着操做而改變,咱們也能夠本身指定狀態:
1 //爲user生成一個DbEntityEntry對象 2 DbEntityEntry userEntry = context.Entry(user); 3 userEntry.State = EntityState.Added;//添加標記 4 userEntry.State = EntityState.Deleted;//刪除標記 5 userEntry.State = EntityState.Modified;//修改標記 6 userEntry.State = EntityState.Unchanged;//無變化標記 7 userEntry.State = EntityState.Detached;//不追蹤標記
狀態間的轉化以下圖:
當DbContext執行SaveChanges()方法時,根據實體的狀態生成相應的Sql語句,經過Ado.net完成數據的持久化。
EF系列目錄連接:Entity Franmework系列教程彙總