You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 06:57:08