NoTracking官方解釋數據庫
跟蹤與非跟蹤查詢
跟蹤行爲可控制 Entity Framework Core 是否將有關實體實例的信息保留在其更改跟蹤器中。 若是已跟蹤某個實體,則該實體中檢測到的任何更改都會在
SaveChanges()
期間永久保存到數據庫。Entity Framework Core 還會修正從跟蹤查詢中獲取的實體與先前已加載到 DbContext 實例中的實體二者之間的導航屬性。 緩存
能夠理解爲:spa
DbContext若是配置爲TrackAll。code
則DbContext會跟蹤返回的實體實例,記錄增刪改查的跟蹤記錄,並自動整合變化,推送Diff Change保留至數據庫。blog
DbContext若是配置爲NoTracking。it
則DBContext不會跟蹤實體變化(再也不自動標記實體變化,但手動標記仍有效),並不自動修正變化。io
1.對增刪改查的影響class
NoTracking 不容許 相同的實體被標記屢次配置
也就是 Attach 的實體必須有不一樣的標記。date
但TrackAll不會有此問題,由於會自動修正2個實體標記
2.查詢緩存
public void Test() { var id = st.T_User.Select(o => o.ID).FirstOrDefault(); using (FLFPermissionEntities ent = dbr.CreateContext<FLFPermissionEntities>()) { using (FLFPermissionEntities sub1 = new FLFPermissionEntities()) { var jm = sub1.FlexUpdate<T_User>(o => o.Name = "lcc", o => o.ID == id); if (jm.HasMsg()) Assert.Fail(jm.msg); } var user21 = ent.T_User.FirstOrDefault(o => o.ID == id); Console.WriteLine($"TrackAllDBContext 第一次讀取:{user21.Name}"); using (FLFPermissionEntities sub2 = new FLFPermissionEntities()) { Console.WriteLine($"改變Name的值爲lcc2"); var jm = sub2.FlexUpdate<T_User>(o => o.Name = "lcc2", o => o.ID == id); if (jm.HasMsg()) Assert.Fail(jm.msg); } var user22 = ent.T_User.FirstOrDefault(o => o.ID == id); Console.WriteLine($"TrackAllDBContext 第二次讀取:{user22.Name}"); } using (FLFPermissionEntities ent = dbr.CreateReadContext<FLFPermissionEntities>()) { using (FLFPermissionEntities sub1 = new FLFPermissionEntities()) { var jm = sub1.FlexUpdate<T_User>(o => o.Name = "lcc", o => o.ID == id); if (jm.HasMsg()) Assert.Fail(jm.msg); } var user21 = ent.T_User.FirstOrDefault(o => o.ID == id); Console.WriteLine($"NoTrackDBContext 第一次讀取:{user21.Name}"); using (FLFPermissionEntities sub2 = new FLFPermissionEntities()) { Console.WriteLine($"改變Name的值爲lcc2"); var jm = sub2.FlexUpdate<T_User>(o => o.Name = "lcc2", o => o.ID == id); if (jm.HasMsg()) Assert.Fail(jm.msg); } var user22 = ent.T_User.FirstOrDefault(o => o.ID == id); Console.WriteLine($"NoTrackDBContext 第二次讀取:{user22.Name}"); } }
NoTrack的結果是正確的,TrackAll的結果與實際結果不一樣
會發現 TrackAll的 2次查詢 結果是同樣的,並且TrackAll的第二次讀取時已經訪問了數據,但出來的結果 仍是lcc 並非lcc2。
因此TrackAll 會從數據庫讀取數據後,根據跟蹤記錄裏的數據信息,覆蓋數據庫中讀取的結果
DbContext 認爲 跟蹤記錄的數據必須統一且數據已跟蹤記錄爲準