EF Core实体更新异常:添加投票后Post.Votes未同步问题
问题:Post.Votes集合未同步新增投票
使用ASP.NET Web API、EF 7和Postgres开发接口,编写了帖子点赞接口。执行后投票表成功新增记录,Post的Content字段也已更新,但调用GET接口获取Posts时,Post.Votes集合并未同步新增的投票。
原添加投票接口
[HttpPost("{id}/Votes")] public async Task<ActionResult> PostVote(PostVoteDTO voteDTO) { PostVote vote = voteDTO.Convert(); Post post = await _dbContext.Posts.FindAsync(voteDTO.PostID); if (post == null) { return NotFound("Post not found"); } post.Votes.Add(vote); post.Content = "Upvoted"; _dbContext.Posts.Update(post); await _dbContext.SaveChangesAsync(); return Ok(); }
获取帖子接口
[HttpGet(Name = "GetPosts")] public async Task<List<Post>> GetPostsAsync() { return await _dbContext.Posts.ToListAsync(); }
VoteDTO定义
public class VoteDTO { [Required] public UpvoteScore Value { get; set; } [Required] public int UserID { get; set; } } public class PostVoteDTO: VoteDTO { [Required] public int PostID { get; set; } public PostVote Convert() { PostVote postVote = new PostVote(); postVote.PostID = PostID; postVote.Value = Value; postVote.UserID = UserID; return postVote; } }
Vote模型定义
public abstract class Vote { [Required] public UpvoteScore Value { get; set; } [Required] public int UserID { get; set; } [ForeignKey("UserID")] public User Voter { get; set; } = null!; } [PrimaryKey(nameof(PostID), nameof(UserID))] public class PostVote : Vote { [Required] public int PostID { get; set; } [ForeignKey("PostID")] public Post Post { get; set; } = null!; } public enum UpvoteScore: short { Downvote = -1, Upvote = 1 }
Post模型定义
[Index(nameof(Title), IsUnique = true)] public class Post { public int PostID { get; set; } [Required] public int PosterID { get; set; } [ForeignKey("PosterID")] public User Poster { get; set; } = null!; public DateTime PostTime { get; set; } [Required] [StringLength(5000)] public string Content { get; set; } = null!; [Required] [StringLength(200)] public string Title { get; set; } = null!; public List<PostVote> Votes { get; set; } public List<Comment> ChildComments { get; set; } public Post() { Votes = new List<PostVote>(); ChildComments = new List<Comment>(); PostTime = DateTime.UtcNow; } }
编辑1
添加ChangeTracker调试后的接口代码:
[HttpPost("{id}/Votes")] public async Task<ActionResult> PostVote(PostVoteDTO voteDTO) { PostVote vote = voteDTO.Convert(); Post post = await _dbContext.Posts.FindAsync(voteDTO.PostID); System.Diagnostics.Debug.WriteLine(_dbContext.ChangeTracker.DebugView.LongView); if (post == null) { return NotFound("Post not found"); } post.Votes.Add(vote); post.Content = "Upvoted Test2"; System.Diagnostics.Debug.WriteLine(_dbContext.ChangeTracker.DebugView.LongView); await _dbContext.SaveChangesAsync(); return Ok(); }
调试输出:
Post {PostID: 1} Unchanged PostID: 1 PK Content: 'Upvoted Test' PostTime: '12/8/2022 2:51:09 PM' PosterID: 1 FK Title: 'bob title' ChildComments: [] Poster: <null> Votes: [] Post {PostID: 1} Unchanged PostID: 1 PK Content: 'Upvoted Test2' Originally 'Upvoted Test' PostTime: '12/8/2022 2:51:09 PM' PosterID: 1 FK Title: 'bob title' ChildComments: [] Poster: <null> Votes: [<not found>]
可见Votes集合从空变为包含<not found>的集合。
编辑2
发现EF Core未跟踪投票实体但已写入数据库,改为直接将投票添加到_dbContext.PostVotes,EF现在可以跟踪Post的变化。修改后的代码:
[HttpPost("{id}/Votes")] public async Task<ActionResult> PostVote(PostVoteDTO voteDTO) { PostVote vote = voteDTO.Convert(); Post post = await _dbContext.Posts.FindAsync(voteDTO.PostID); System.Diagnostics.Debug.WriteLine(_dbContext.ChangeTracker.DebugView.LongView); if (post == null) { return NotFound("Post not found"); } await _dbContext.PostVotes.AddAsync(vote); System.Diagnostics.Debug.WriteLine(_dbContext.ChangeTracker.DebugView.LongView); await _dbContext.SaveChangesAsync(); return Ok(); }
内容的提问来源于stack exchange,提问作者Pap113
相关产品推荐
相关产品推荐

