ASP.NET Core 6.0 Web API:EF Core延迟加载代理下无法更新数据库
问题:EF Core 6.0 创建用户时数据库不更新但能正常查询
环境与配置
使用EF Core 6.0延迟加载功能,已安装Microsoft.EntityFrameworkCore.Proxies包,DbContext配置如下:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { optionsBuilder.UseLazyLoadingProxies().UseSqlServer("Server = SRV84; Database = BASE_DEMO1; User Id = sa; Password = Ab@123456"); } }
API核心代码
创建用户接口(POST)
[HttpPost] public async Task<IActionResult> CreateUser(UserCreateDto oUserCreate) { var oUser = await _authorizationService.GetUserByUserName(oUserCreate.Username); if (oUser.Id > 0) { return BadRequest("Username already exists"); } oUserCreate.Status = (int)StatusUser.Deactive; oUserCreate.CreatedDate = DateTime.Now; oUserCreate.ModifiedDate = DateTime.Now; oUserCreate.Status = (int)StatusUser.Deactive; var idUser = await _authorizationService.CreateUser(oUserCreate); if (idUser == 0) { await AddLogAsync(UserIdentity.FullName + ": create " + oUserCreate.FullName, OBJECT.USERS, (int)ActionLogs.Add, (int)StatusLogs.Error); return BadRequest("There was an error!"); } await AddLogAsync(UserIdentity.FullName + ": create " + oUserCreate.FullName, OBJECT.USERS, (int)ActionLogs.Add, (int)StatusLogs.Success); #region Create new Userinfo UserInfoCreateDto userInfo = new UserInfoCreateDto(); userInfo.Address = oUserCreate.Address; userInfo.Email = oUserCreate.Email; userInfo.Avatar = oUserCreate.Avatar; userInfo.Phone = oUserCreate.PhoneNumber; userInfo.Sex = oUserCreate.Sex; userInfo.UserId = idUser; await BaseService.CreateAsync<UserDetail, UserInfoCreateDto>(userInfo); #endregion #region Create new Group if (oUserCreate.GroupIds.Count > 0) { foreach (var item in oUserCreate.GroupIds) { if (item > 0) { await BaseService.CreateAsync<GroupUser, GroupUserCreateDto>(new GroupUserCreateDto() { GroupId = item, UserId = idUser }); } } } #endregion return Ok(); }
查询用户接口(GET)
[HttpGet] public async Task<IActionResult> GetUsers([FromQuery] UserGridPagingDto pagingModel) { var predicates = pagingModel.GetPredicates(); var result = await BaseService.FilterPagedAsync<User, UserGridDto>(pagingModel, predicates.ToArray()); if (pagingModel.GroupId > 0) { if (result.Data.Count > 0) { for (int i = 0; i < result.Data.Count; i++) { result.Data[i].IsCheck = result.Data[i].LstGroupIds.Contains(pagingModel.GroupId); } } } return Ok(result); }
问题现象
调用POST接口创建用户时,数据库无任何更新,但GET接口能正常返回之前添加的旧数据;尝试删除数据库、注释连接字符串并重启电脑后,仍能获取到旧数据。
终端日志输出
16' with options: using lazy loading proxies info: Microsoft.EntityFrameworkCore.Database.Command[20101] Executed DbCommand (52ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] SELECT COUNT(*) FROM [Users] AS [u] WHERE [u].[DeletedUserId] IS NULL info: Microsoft.EntityFrameworkCore.Database.Command[20101] Executed DbCommand (52ms) [Parameters=[@__p_0='?' (DbType = Int32)], CommandType='Text', CommandTimeout='30'] SELECT [t].[Id], [t].[UserName], [t].[FullName], [t].[c], [t].[Status], [t].[CreatedDate], [t].[DeletedUserId], [t].[c0], [g].[GroupId], [g].[Id] FROM ( SELECT TOP(@__p_0) [u].[Id], [u].[UserName], [u].[FullName], ( SELECT TOP(1) [u0].[Email] FROM [UserDetail] AS [u0] WHERE [u].[Id] = [u0].[UserId]) AS [c], [u].[Status], [u].[CreatedDate], [u].[DeletedUserId], ( SELECT TOP(1) [u1].[Phone] FROM [UserDetail] AS [u1] WHERE [u].[Id] = [u1].[UserId]) AS [c0] FROM [Users] AS [u] WHERE [u].[DeletedUserId] IS NULL ORDER BY [u].[Id] DESC ) AS [t] LEFT JOIN [GroupUser] AS [g] ON [t].[Id] = [g].[UserId] ORDER BY [t].[Id] DESC
解决方案
- 检查服务层的保存操作:
确认_authorizationService.CreateUser和BaseService.CreateAsync内部是否调用了await _context.SaveChangesAsync()。基础服务封装时若遗漏此步骤,实体仅会被添加到内存上下文,不会同步到数据库。 - 验证连接字符串的有效性:
删除数据库后仍能获取旧数据,说明程序可能连接到了其他数据库实例。可在OnConfiguring中添加日志输出当前连接字符串,或直接登录SQL Server查看BASE_DEMO1数据库的实时数据,确认是否真的没有写入。 - 排查是否使用内存数据库:
检查项目启动配置(如Program.cs),确认是否意外注册了内存数据库(UseInMemoryDatabase)。若使用内存数据库,所有操作仅在内存中进行,重启后数据不会持久化,但旧数据可能来自之前的内存缓存。 - 检查事务与异常处理:
确认创建用户、用户信息、用户组的操作是否在同一事务中,是否有异常被吞导致事务回滚。可打印idUser的值,以及后续CreateAsync的执行结果,排查是否有步骤失败。 - 验证实体主键配置:
检查User、UserDetail、GroupUser实体的主键是否正确配置为自增(如[Key]+[DatabaseGenerated(DatabaseGeneratedOption.Identity)])。若主键未正确配置,插入时无法生成有效ID,会导致关联数据无法写入,甚至整个插入操作失败。
内容的提问来源于stack exchange,提问作者Levi Ackerman
相关产品推荐
相关产品推荐

