C# 无法使用asp.net core 2.2应用程序中的ef core 2.2通过UserManager更新用户

C# 无法使用asp.net core 2.2应用程序中的ef core 2.2通过UserManager更新用户,c#,repository-pattern,asp.net-core-2.2,asp.net-core-identity,ef-core-2.2,C#,Repository Pattern,Asp.net Core 2.2,Asp.net Core Identity,Ef Core 2.2,我正在尝试使用UserManager更新用户,但出现以下错误 无法跟踪实体类型“UserEntity”的实例,因为 已在跟踪另一个键值为“{Id}”的实例。 附着现有实体时,请确保仅包含一个实体实例 附加了一个给定的键值 关于上述错误,互联网上有几个问题,但在通过UserManager更新用户时没有问题 这是我的密码: 服务配置: services.AddScoped; 服务附加性 .AddEntityFrameworkStores .AddDefaultTokenProviders; 用户实体

我正在尝试使用UserManager更新用户,但出现以下错误

无法跟踪实体类型“UserEntity”的实例,因为 已在跟踪另一个键值为“{Id}”的实例。 附着现有实体时,请确保仅包含一个实体实例 附加了一个给定的键值

关于上述错误,互联网上有几个问题,但在通过UserManager更新用户时没有问题

这是我的密码:

服务配置:

services.AddScoped; 服务附加性 .AddEntityFrameworkStores .AddDefaultTokenProviders; 用户实体:

公共类UserEntity:IdentityUser { 私人档案实体_档案; 私有用户EntityIlazyLoader lazyLoader { 懒汉=懒汉; } 私有ILazyLoader LazyLoader{get;set;} 公共用户实体 { } 公共字符串名{get;set;} 公共字符串LastName{get;set;} 公共字符串名称{get;set;} 公共字符串标识符编号{get;set;} 公共bool活动{get;set;} public DateTimeOffset CreatedAt{get;set;} 通过{get;set;}创建的公共字符串 public DateTimeOffset?ModifiedAt{get;set;} 公共字符串由{get;set;}修改 公共Guid配置文件ID{get;set;} 公共配置文件实体配置文件{get=>LazyLoader.Loadthis,ref{u Profile;set=>{u Profile=value;} } Razor页面处理程序:

公共异步任务OnPutAsync [FromForm]用户视图模型用户视图模型, 取消令牌ct { 尝试 { 等待_user.initializeAsyncUserModel.Id,ct; var user=\u mapper.MapuserViewModel,\u user; var result=await user.SaveAsyncct; 返回新的JsonResultnew AjaxResultPerResult。成功 { Response=result.ErrorMessage→ResponseMessages.DataSaved }; } 捕获异常e { //需要记录错误 返回新的JsonResultnew AjaxResultPer { 响应=e.消息 }; } } 用户业务:

公共类用户:CoreEntityBase { 专用只读IUserRepository\u userRepository; 专用只读IMapper\u映射器; 公共用户 IUserRepository用户存储库, IMapper映射器 { _userRepository=userRepository; _映射器=映射器; } 公共字符串名称=>${FirstName}{LastName}; 公共字符串用户名{get;private set;} 公共字符串NormalizedUserName{get;private set;} 公共字符串电子邮件{get;private set;} 公共字符串NormalizedEmail{get;private set;} 公共布尔值{get;private set;} 公共字符串密码哈希{get;private set;} 公共字符串SecurityStamp{get;private set;} 公共字符串并发amp{get;private set;} public bool LockoutEnabled{get;private set;} [SortableDefault=true] [可搜索字符串] 公共字符串名{get;set;} [可排序] [可搜索字符串] 公共字符串LastName{get;set;} [可排序] [可搜索字符串] 公共字符串名称{get;set;} [可排序] [可搜索字符串] 公共字符串标识符编号{get;set;} 公共Guid配置文件ID{get;set;} [嵌套排序] [可嵌套搜索] 公共配置文件{get;set;} 公共异步任务初始化同步 Guid Id, 取消令牌ct { 如果Id==null { 抛出新ArgumentNullException${nameofId}不能为null; } var user=await_userRepository.GetUserByIdAsyncId,ct; _mapper.Mapuser,这个; SecurityStamp=user.SecurityStamp; 用户名=user.UserName; } 公共异步任务GetUserByIdAsync Guid用户ID, 取消令牌ct { var user=await_userRepository.GetUserByIdAsyncuserId,ct; 返回_mapper.Mapuser; } 公共异步任务SaveAsyncCancellationToken ct { 如果!验证 { 返回false,错误?。首先; } //var userEntity=await_userRepository.GetUserByIdAsyncId,ct; //var userEntity=\u mapper.Mapthis,userEntity; var update=await\u userRepository.updateUserSyncThis; 返回 日期 } 公共覆盖布尔验证 { var isValid=true; 如果string.IsNullOrWhiteSpaceFirstName { Errors.AddFirstName不能为空; isValid=false; } 如果string.IsNullOrWhiteSpaceLastName { Errors.AddLastName不能为空; isValid=false; } 如果string.IsNullOrWhiteSpaceDesignation { Errors.AddDesignation不能为空; isValid=false; } 返回有效; } } 用户存储库:

公共类UserRepository:IUserRepository { 私有只读用户管理器_UserManager; 专用只读IMapper\u映射器; 公共用户存储库 用户管理器用户管理器, IMapper映射器 { _userManager=userManager; _映射器=映射器; } 公共异步任务GetUserByIdAsync Guid用户ID, 取消令牌ct { var entity=await_userManager.Users.AsNoTracking.TagWithnameofGetUserIdAsync .Includeu=>美国概况 .SingleOrDefaultAsyncx=>x.Id==userId,ct; 返回实体; } 公共异步任务UpdateUserAsyncUser用户 { var userEntity=\u mapper.Mapuser; var result=await\u userManager.UpdateAsyncuserEntity; 如果结果是成功的 { 返回true,null; } var firstError=result.Errors.FirstOrDefault?.Description; 返回false,firstError; } } 我不知道我错在哪里。我在GetUserByIdAsync方法中为_userManager.Users设置了AsNoTracking;但它仍然不起作用,并不断抛出相同的错误。我做得不对吗?请帮助我纠正哪些地方需要纠正,以及我哪里出了问题


提前感谢。

经过一些分析,解决了这个问题。这是因为GetUserByIdAsync。虽然我将其设置为notracking to _userManager.Users,但ef core会对其进行内部跟踪。因此,将实现更改为通过_userManager.FindByIdAsync返回用户,这就成功了

这是最终清理的代码。希望这对别人有帮助

Razor页面处理程序:

公共异步任务OnPutAsync[FromForm]UserViewModel UserViewModel { 尝试 { wait_user.initializeAsyncuservewModel.Id; var user=\u mapper.MapuserViewModel,\u user; var成功,ErrorMessage=await user.SaveAsync; 返回新的JsonResultnew AjaxResultPersucceeded { Response=ErrorMessage??ResponseMessages.DataSaved }; } 捕获异常 { //需要记录错误 Console.WriteLineex.Message; 返回新的JsonResultnew AjaxResultPer { Response=ResponseMessages.DataNotSaved }; } } 用户业务:

公共类用户:CoreEntityBase { 专用只读IUserRepository\u userRepository; 专用只读IMapper\u映射器; 公共用户 { } 公共用户 IUserRepository用户存储库, IMapper映射器 { _userRepository=userRepository; _映射器=映射器; } 公共字符串名称{get;set;} [SortableDefault=true] [可搜索字符串] 公共字符串名{get;set;} [可排序] [可搜索字符串] 公共字符串LastName{get;set;} [可排序] [可搜索字符串] 公共字符串名称{get;set;} [可排序] [可搜索字符串] 公共字符串标识符编号{get;set;} 公共Guid配置文件ID{get;set;} [嵌套排序] [可嵌套搜索] 公共配置文件{get;set;} 公共异步任务InitializeAsyncGuid Id { 如果Id==null { 抛出新ArgumentNullException${nameofId}不能为null; } var userEntity=await_userRepository.GetUserByIdAsyncId; _mapper.MapuserEntity,此; } 公共异步任务GetUsersAsync 分页选项分页选项, 分类分类分类, 搜索选项搜索选项, 取消令牌ct { var users=await_userRepository.getusersasyncpagingpoptions、sortOptions、searchOptions、ct; 返回新页面结果 { Items=\u mapper.Mapusers.Items, TotalSize=users.TotalSize }; } 公共异步任务GetUserByIdAsyncGuid使用 摆脱 { var userEntity=await_userRepository.GetUserByIdAsyncuserId; 返回_mapper.MapuserEntity; } 公共异步任务SaveAsync { 如果!验证 { 返回false,错误; } var userEntity=await_userRepository.GetUserByIdAsyncId; userEntity=\u mapper.Mapthis,userEntity; var update=await\u userRepository.updateUserSyncUserEntity; 返回更新; } 公共覆盖布尔验证 { var isValid=true; 如果string.IsNullOrWhiteSpaceFirstName { 错误=FirstName不能为空; isValid=false; } 如果string.IsNullOrWhiteSpaceLastName { 错误=LastName不能为空; isValid=false; } 如果string.IsNullOrWhiteSpaceDesignation { 错误=名称不能为空; isValid=false; } 返回有效; } } 用户存储库:

公共类UserRepository:IUserRepository { 私有只读用户管理器_UserManager; 公共用户存储库 用户管理器用户管理器 { _userManager=userManager; } 公共异步任务GetUserByIdAsyncGuid userId { var entity=await\u userManager.FindByIdAsyncuserId.ToString; 返回实体; } 公共异步任务UpdateUserSyncUserEntity用户实体 { var result=await\u userManager.UpdateAsyncuserEntity; 如果结果是成功的 { 返回true,null; } var firstError=result.Errors.FirstOrDefault?.Description; 返回false,firstError; } }
经过一番分析后,我发现了这个问题。这是因为GetUserByIdAsync。虽然我将其设置为notracking to _userManager.Users,但ef core会对其进行内部跟踪。因此,将实现更改为通过_userManager.FindByIdAsync返回用户,这就成功了

这是最终清理的代码。希望这对别人有帮助

Razor页面处理程序:

公共异步任务OnPutAsync[FromForm]UserViewModel UserViewModel { 尝试 { wait_user.initializeAsyncuservewModel.Id; var user=\u mapper.MapuserViewModel,\u user; var成功,ErrorMessage=await user.SaveAsync; 返回新的JsonResultnew AjaxResultPersucceeded { Response=ErrorMessage??ResponseMessages.DataSaved }; } 捕获异常 { //需要记录错误 Console.WriteLineex.Message; 返回新的JsonResultnew AjaxResultPer { Response=ResponseMessages.DataNotSaved }; } } 用户业务:

公共类用户:CoreEntityBase { 专用只读IUserRepository\u userRepository; 专用只读IMapper\u映射器; 公共用户 { } 公共用户 IUserRepository用户存储库, IMapper映射器 { _userRepository=userRepository; _映射器=映射器; } 公共字符串名称{get;set;} [SortableDefault=true] [可搜索字符串] 公共字符串名{get;set;} [可排序] [可搜索字符串] 公共字符串LastName{get;set;} [可排序] [可搜索字符串] 公共字符串名称{get;set;} [可排序] [可搜索字符串] 公共字符串标识符编号{get;set;} 公共Guid配置文件ID{get;set;} [嵌套排序] [可嵌套搜索] 公共配置文件{get;set;} 公共异步任务InitializeAsyncGuid Id { 如果Id==null { 抛出新ArgumentNullException${nameofId}不能为null; } var userEntity=await_userRepository.GetUserByIdAsyncId; _mapper.MapuserEntity,此; } 公共异步任务GetUsersAsync 分页选项分页选项, 分类分类分类, 搜索选项搜索选项, 取消令牌ct { var users=await_userRepository.getusersasyncpagingpoptions、sortOptions、searchOptions、ct; 返回新页面结果 { Items=\u mapper.Mapusers.Items, TotalSize=users.TotalSize }; } 公共异步任务GetUserByIdAsyncGuid userId { var userEntity=await_userRepository.GetUserByIdAsyncuserId; 返回_mapper.M apuserEntity; } 公共异步任务SaveAsync { 如果!验证 { 返回false,错误; } var userEntity=await_userRepository.GetUserByIdAsyncId; userEntity=\u mapper.Mapthis,userEntity; var update=await\u userRepository.updateUserSyncUserEntity; 返回更新; } 公共覆盖布尔验证 { var isValid=true; 如果string.IsNullOrWhiteSpaceFirstName { 错误=FirstName不能为空; isValid=false; } 如果string.IsNullOrWhiteSpaceLastName { 错误=LastName不能为空; isValid=false; } 如果string.IsNullOrWhiteSpaceDesignation { 错误=名称不能为空; isValid=false; } 返回有效; } } 用户存储库:

公共类UserRepository:IUserRepository { 私有只读用户管理器_UserManager; 公共用户存储库 用户管理器用户管理器 { _userManager=userManager; } 公共异步任务GetUserByIdAsyncGuid userId { var entity=await\u userManager.FindByIdAsyncuserId.ToString; 返回实体; } 公共异步任务UpdateUserSyncUserEntity用户实体 { var result=await\u userManager.UpdateAsyncuserEntity; 如果结果是成功的 { 返回true,null; } var firstError=result.Errors.FirstOrDefault?.Description; 返回false,firstError; } }
我不建议创建一个知道如何从注入的存储库初始化自身的用户类。这违反了SRP和IMO,这是您看到的问题的一部分。听起来您在UserManager中通过EF跟踪找到了问题的根源。查看实体是如何在中使用的,看看我如何保持实体持久性,即使在存储库中也是如此。感谢Smith的指点。我有这个疑问。所以我不应该在构造函数中传递存储库?关于属性映射,我应该直接在构造函数中传递所有属性,在构造函数中传递映射,或者我可以使用mapper来实现这一点?使用mapper会带来不必要的依赖性?我不建议创建知道如何从注入的存储库初始化自身的用户类。这违反了SRP和IMO,这是您看到的问题的一部分。听起来您在UserManager中通过EF跟踪找到了问题的根源。查看实体是如何在中使用的,看看我如何保持实体持久性,即使在存储库中也是如此。感谢Smith的指点。我有这个疑问。所以我不应该在构造函数中传递存储库?关于属性映射,我应该直接在构造函数中传递所有属性,在构造函数中传递映射,或者我可以使用mapper来实现这一点?使用mapper会带来不必要的依赖性吗?