EF的 NoTracking 的一些記錄

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 認爲 跟蹤記錄的數據必須統一且數據已跟蹤記錄爲準

相關文章
相關標籤/搜索