代码优先实体框架 - 评论评论功能,相同的评论显示两次

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了代码优先实体框架 - 评论评论功能,相同的评论显示两次相关的知识,希望对你有一定的参考价值。

我正在撰写评论功能。你可以评论一个线程。你也可以对评论发表评论。因此,Thread有一个注释列表,每个注释都有一个注释列表:

public class Thread
{
    public int ThreadId { get; set; }

    public int PostId { get; set; }

    public virtual List<Comment> Comments { get; set; }
}


public class Comment
{
    public int CommentId { get; set; }

    [MaxLength(280)]
    public string Content { get; set; }

    public long time { get; set; } // unix time / epoch time

    [JsonIgnore]
    [IgnoreDataMember]
    public string user_id { get; set; }
    public virtual CommentUser CommentUser { get; set; }

    [JsonIgnore]
    [IgnoreDataMember]
    public int ThreadId { get; set; }

    [JsonIgnore]
    [IgnoreDataMember]
    public virtual Thread Thread { get; set; }

    public virtual List<Comment> Comments { get; set; }

}

我遇到的问题是当我评论某个帖子然后评论该评论时。所以总共有两条评论。

我得到了这个JSON,有三条评论:

{
  "ThreadId": 3,
  "Comments": [
    {
      "Comments": [
        {
          "Comments": [],
          "CommentUser": {
            "user_id": "123",
            "nickname": "user",
          },
          "CommentId": 52,
          "Content": "comment on comment",
          "time": 1513784459
        }
      ],
      "CommentUser": {
        "user_id": "123",
        "nickname": "user",
      },
      "CommentId": 51,
      "Content": "asdf asdf asd f",
      "time": 1513784447
    },
    {
      // THIS COMMENT SHOULD NOT SHOW UP HERE
      "Comments": [],
      "CommentUser": {
        "user_id": "123",
        "nickname": "user",
      },
      "CommentId": 52,
      "Content": "comment on comment",
      "time": 1513784459
    }
  ]
}

这就是DB的样子,只有两条评论:

comments db

获取线程的方法非常简单:

        Thread commentThread = await (from t in db.Thread where t.PostId == tr.postId select t).FirstOrDefaultAsync();

        return Json(commentThread);

我很难弄清楚哪里出了问题。任何帮助赞赏!

答案

正如@Ivan和@Olivier在他们的评论中提到的那样,这是因为Comment实体与所有者Thread有直接关系(必需),而与级别无关。

基本上,当你执行你的linq查询时,结果是带有两个ThreadComments对象。第二个是您在第一条评论评论中可以看到的相同评论。哦,孩子,这是一口。

像这样的东西:

commentThread.Comments = Comment[]

    //first comment from thread
    {
        "CommentId": 1,
        "Content": "Thread comment",

            "Comments": [
                //This is the same comment (Id = 2) being fetched from both Thread and Comment entities.
                {
                    "CommentId": 2,
                    "Content": "Comment on comment"
                }
        ] 
    },

    //second comment from thread
    {
        "CommentId": 2,
        "Content": "Comment on comment"
    }
]

避免此问题的一种方法是仅从顶级注释引用线程,并在所有嵌套注释上将ThreadId设置为null。这将为您提供最佳结果,因为您的查询将保持干净(即您不需要更改代码来过滤或排除,也不需要检查是否有引用的注释)。

但是你当前的模型不允许这样,因为你的ThreadId是一个int。根据您向我们展示的模型数量,这应该相对容易实现。所以只需将属性ThreadId设置为int?

public class Comment
{
    public int CommentId { get; set; }

    [MaxLength(280)]
    public string Content { get; set; }

    public long time { get; set; } // unix time / epoch time

    [JsonIgnore]
    [IgnoreDataMember]
    public string user_id { get; set; }
    public virtual CommentUser CommentUser { get; set; }

    [JsonIgnore]
    [IgnoreDataMember]
    public int? ThreadId { get; set; } 
              ^ //set this as nullable

    [JsonIgnore]
    [IgnoreDataMember]
    public virtual Thread Thread { get; set; }

    public virtual List<Comment> Comments { get; set; }

}

运行迁移并更新您的Db(或获取DBA的脚本):

add-migration SetThreadIdAsNullable

update-database或update-database -script

你应该好好去。查询现在应该返回thread对象只有一个comment,而comment应该包含一个嵌套的Thread,如你想要实现的那样。

希望这可以帮助!

另一答案

这是ThreadId = 3实体的通常行为。因为,在评论表中有两个记录与Comment_CommentId。所以,你应该删除public static class ThreadExtensions { public static IQueryable<Thread> GetThreadAsQueryable(this DbSet<Thread> table) { return table.Where(x => x.Comments.Where(x => x.Comment_CommentId == null)); } } using (var context = new SampleDbContext()) { var str = context.Thread.GetThreadAsQueryable().ToList(); } 不为空的评论记录。所以,也许你可以用扩展方法过滤它;

HasQueryFilter

此外,有一个功能名为it for EfCore 2.0。我认为,它完全满足需要。如果您使用EfCore 2.0,我建议您检查qazxswpoi。

以上是关于代码优先实体框架 - 评论评论功能,相同的评论显示两次的主要内容,如果未能解决你的问题,请参考以下文章

评论回复功能设计

第一阶段意见评论

文章详情页文章评论功能

基于Spring+SpringMVC+MyBatis开发书评网图书详情页-显示评论列表开发

Spring Boot制作个人博客-框架搭建(设计与规范,实体类构建)

Java单表实现评论回复功能