.NET7 MongoDB EF插入赛事时UserId为空ObjectId问题排查
问题:MongoDB EF Core插入赛事时UserId存储为空ObjectId
我使用C# .NET7结合MongoDB Entity Framework开发国际象棋赛事WebAPI,遇到一个问题:插入关联用户的赛事时,MongoDB中的UserId字段总是被存储为ObjectId('000000000000000000000000'),而非实际的用户ID。
我的Tournament模型定义了ObjectId?类型的UserId字段,服务层与控制器实现了赛事添加逻辑,前端TypeScript脚本获取用户ID后组装赛事数据发起POST请求,日志显示userId已正确赋值,但数据库中仍为空ObjectId,寻求解决建议。
相关代码
TournamentModel.cs
public enum TournamentStatus { Planned, Ongoing, Finished, } public enum TournamentType { Classic, Rapid, Blitz, Bullet } [Collection("tournaments")] public class Tournament { public ObjectId Id { get; set; } public ObjectId? UserId { get; set; } [Required(ErrorMessage ="Title is required")] public string Title { get; set; } public string EventUrl { get; set; } public string County { get; set; } [Required(ErrorMessage = "Status is required")] public TournamentStatus Status { get; set; } [Required(ErrorMessage ="Provide type of tournament")] public TournamentType Type { get; set; } [Required(ErrorMessage = "Provide information whether the tournament is FIDE classified")] public Boolean IsFide { get; set; } [Required(ErrorMessage ="Provide details for tournament")] public TournamentDetails Details { get; set; } }
TournamentService.cs 添加逻辑
public void AddTournament(Tournament newTournament) { _BCAContextDb.Tournaments.Add(newTournament); _BCAContextDb.ChangeTracker.DetectChanges(); Console.WriteLine(_BCAContextDb.ChangeTracker.DebugView.LongView); _BCAContextDb.SaveChanges(); }
TournamentController.cs POST逻辑
[HttpPost] public ActionResult<Tournament> PostTournament(Tournament tournament) { _tournamentService.AddTournament(tournament); return CreatedAtAction(nameof(GetTournamentById), new { id = tournament.Id }, tournament); }
前端TypeScript脚本
const agent = new https.Agent({ rejectUnauthorized: false, }); let tournament = { userId:{}, title: "string", eventUrl: "string", county: "string", status: 0, type: 0, isFide: true, details: { startDate: "2024-03-13T18:53:41.465Z", endDate: "2024-03-13T18:53:41.465Z", place: "string", gameTempo: "string", referee: "string", organizer: "string", roundsTotal: 0, roundsEnded: 0, gameSystem: "string", }, }; const grabData = async () => { try { const response = await axios.get("https://localhost:7001/api/user", { httpsAgent: agent }); const id = response.data[0].id; console.log(id); return id; } catch (error) { console.error("Error:", error.message); throw error; } }; const main = async () => { try { const userId = await grabData(); tournament.userId = userId; const tournamentToPush = tournament; console.log("Tournament pushed:", tournamentToPush); const response = await axios.post("https://localhost:7001/api/tournament", tournamentToPush, { httpsAgent: agent }); console.log("Tournament created:", response.data); } catch (error) { console.error("Error:", error.message); } }; main();
解决建议
修复ObjectId与字符串的序列化映射
前端传递的用户ID是字符串格式,后端ObjectId类型无法自动解析,导致被初始化为空ObjectId。在模型的UserId字段添加特性,让MongoDB EF Core自动处理字符串到ObjectId的转换:[BsonRepresentation(BsonType.ObjectId)] public ObjectId? UserId { get; set; }修正前端数据初始格式
前端初始定义tournament.userId为{},可能导致序列化异常。改为字符串类型:let tournament = { userId: "", // 替换原空对象 // ...其他字段 };使用DTO接收前端数据(推荐)
避免直接用实体类处理序列化,新增DTO类接收字符串ID,手动转换为ObjectId:// 新增DTO public class TournamentDto { public string UserId { get; set; } // 复制Tournament类的其他字段 } // 修改控制器逻辑 [HttpPost] public ActionResult<Tournament> PostTournament([FromBody] TournamentDto tournamentDto) { var tournament = new Tournament { UserId = ObjectId.TryParse(tournamentDto.UserId, out var objId) ? objId : null, Title = tournamentDto.Title, Status = tournamentDto.Status, // 映射其他字段 }; _tournamentService.AddTournament(tournament); return CreatedAtAction(nameof(GetTournamentById), new { id = tournament.Id }, tournament); }验证ChangeTracker日志细节
仔细查看ChangeTracker.DebugView.LongView的输出,确认UserId的实际值是否为有效ObjectId。如果日志中显示为字符串,说明序列化未完成转换,需优先处理序列化配置。
内容的提问来源于stack exchange,提问作者Piotrek940
相关产品推荐
相关产品推荐

