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();
更多精彩内容,请关注我的V信公众号:程序员不帅哥