FluentValidator配合DbContext使用编辑用户报实体追踪冲突如何解决?
问题原因
你遇到的实体追踪冲突是同一请求内共享MvcUserContext实例导致的:
- 默认配置下
MvcUserContext是请求作用域生命周期,同一个HTTP请求中,UserValidator和UsersController注入的是同一个上下文实例 - 执行Edit方法的模型验证阶段,
UserValidator的uniqueMail/uniquePhone方法会从数据库查询匹配邮箱/手机号的User实体,EF Core默认会将查询到的实体加入上下文追踪器 - 验证通过后执行
_context.Update(user)时,传入的user是模型绑定生成的全新实例,和之前验证阶段查询到的同Id实体冲突,因此抛出重复追踪的异常 - 创建/删除功能正常的原因:新增用户时Id为默认值,验证阶段不会查询到匹配实体,不会触发追踪;删除操作不会绑定完整User实体,不会触发该唯一性校验,因此没有冲突。
解决方案
推荐采用无实体查询方案,直接判断是否存在重复记录,不需要加载完整实体,从根源避免追踪问题,同时查询效率更高:
修改UserValidator的两个校验方法:
private bool uniqueMail(User user, string email) { return !_context.User.Any(x => x.Email.Equals(email, StringComparison.OrdinalIgnoreCase) && x.Id != user.Id); } private bool uniquePhone(User user, string phone) { return !_context.User.Any(x => x.Phone == phone && x.Id != user.Id); }
如果需要保留原有查询逻辑,也可以在查询时加上AsNoTracking关闭实体追踪即可:
var mail = _context.User.AsNoTracking().Where(x => x.Email.ToLower() == user.Email.ToLower()).SingleOrDefault();
内容的提问来源于stack exchange,提问作者Orbey Paltaci
相关产品推荐
相关产品推荐

