1. 程式人生 > 實用技巧 >Entity Framework 更新失敗,除錯後發現是AsNoTracking的原因

Entity Framework 更新失敗,除錯後發現是AsNoTracking的原因

public override int SaveChanges()
        {
            var changedEntities = ChangeTracker.Entries().Where(e => e.State == EntityState.Added || e.State == EntityState.Modified).ToList();
            var now = DateTime.Now;
            changedEntities.ForEach(e =>
            {
                
if (e.State == EntityState.Added) { var createTimeProperty = e.Entity.GetType().GetProperty("CreateTime"); var createUserIdProperty = e.Entity.GetType().GetProperty("CreateUserId"); var createUserNameProperty = e.Entity.GetType().GetProperty("
CreateUserName"); if (createTimeProperty != null) { createTimeProperty.SetValue(e.Entity, now); } if (createUserIdProperty != null) { createUserIdProperty.SetValue(e.Entity, InternalContext.UserId); }
if (createUserNameProperty != null) { createUserNameProperty.SetValue(e.Entity, InternalContext.UserName); } var updateTimeProperty = e.Entity.GetType().GetProperty("UpdateTime"); var updateUserIdProperty = e.Entity.GetType().GetProperty("UpdateUserId"); var updateUserNameProperty = e.Entity.GetType().GetProperty("UpdateUserName"); if (updateTimeProperty != null) { updateTimeProperty.SetValue(e.Entity, now); } if (updateUserIdProperty != null) { updateUserIdProperty.SetValue(e.Entity, InternalContext.UserId); } if (updateUserNameProperty != null) { updateUserNameProperty.SetValue(e.Entity, InternalContext.UserName); } } else if (e.State == EntityState.Modified) { var isDeleteProperty = e.Entity.GetType().GetProperty("IsDelete"); if (isDeleteProperty != null && (bool)isDeleteProperty.GetValue(e.Entity)) { var deleteTimeProperty = e.Entity.GetType().GetProperty("DeleteTime"); var deleteUserIdProperty = e.Entity.GetType().GetProperty("DeleteUserId"); var deleteUserNameProperty = e.Entity.GetType().GetProperty("DeleteUserName"); if (deleteTimeProperty != null) { deleteTimeProperty.SetValue(e.Entity, now); } if (deleteUserIdProperty != null) { deleteUserIdProperty.SetValue(e.Entity, InternalContext.UserId); } if (deleteUserNameProperty != null) { deleteUserNameProperty.SetValue(e.Entity, InternalContext.UserName); } } else { var updateTimeProperty = e.Entity.GetType().GetProperty("UpdateTime"); var updateUserIdProperty = e.Entity.GetType().GetProperty("UpdateUserId"); var updateUserNameProperty = e.Entity.GetType().GetProperty("UpdateUserName"); if (updateTimeProperty != null) { updateTimeProperty.SetValue(e.Entity, now); } if (updateUserIdProperty != null) { updateUserIdProperty.SetValue(e.Entity, InternalContext.UserId); } if (updateUserNameProperty != null) { updateUserNameProperty.SetValue(e.Entity, InternalContext.UserName); } } } }); return base.SaveChanges(); }

先看以上程式碼,我們封裝了一個SaveChanges的方法,用來提交實體的修改或插入操作,這個操作有個好處就是不用寫事務,如果你需要插入多張表,並且是要麼全部成功,要麼全部失敗,那使用這個方法就很方便了。

不過今天遇到一個更新的問題,始終沒有報錯,但就是無法更新。

後來除錯程式碼,發現一個很關鍵的地方:AsNoTracking()

針對查詢,在一些情況下,我們只需要返回一個只讀的資料就可以,並不會對資料記錄進行任何的修改。

這種時候不希望Entity Framework進行不必要的狀態變動跟蹤,可以使用Entity Framework(EFCore中也有哦)的AsNoTracking方法來查詢返回不帶變動跟蹤的查詢結果

由於是無變動跟蹤,所以對返回的資料的沒有進行任何修改,在SaveChanges()時,都不會提交到資料庫中。

所以,我上圖中的程式碼雖然下面修改了IsDelete=true,但是我在查詢的時候已經加入了AsNoTracking,當我SaveChange的時候,這個修改並不會被提交,所以無法完成更新。

我們在做資料集合查詢顯示,而又不需要對集合修改並更新到資料庫的時候,

一定不要忘記加上AsNoTracking。

如果查詢過程做了select對映不需要加AsNoTracking

如:db.user.Where(t=>t.Name.Contains("小明")).select(t=>new (t.Name,t.Age)).ToList();