使用ASP.NET MVC 4(嵌套集合)创建博客评论和回复部分

本文关键字:创建 评论 回复部 集合 NET ASP MVC 嵌套 使用 | 更新日期: 2023-09-27 18:20:45

我正在构建一个博客评论和回复部分,我将这三个类映射到我的DB。第一类保存文章的相关评论的集合,第二类保存评论的相关评论集合:

public class Article
{
    public int ArticleID { get; set; }
    public byte[] Image { get; set; }
    public string Title { get; set; }
    public string Body { get; set; }
    public DateTime DatePublished { get; set;  }
    public string Author { get; set; }
    public CategoryTyp Category { get; set; }
    public virtual ICollection<Comment> Comments { get; set; }
}
public class Comment
{
    public int CommentID { get; set; }
    public int ArticleID { get; set; }
    public int CategoryID { get; set; }
    public int UserID { get; set; }
    public string Description { get; set; }
    public DateTime CommentDate { get; set; }
    public virtual ICollection<Remark> Remarks { get; set; }
}
public class Remark
{
    public int RemarkID { get; set; }
    public int CommentID { get; set; }
    public int ArticleID { get; set; }
    public string RemarkDetail { get; set; }
    public DateTime RemarkTime { get; set;  }
}

在我的控制器里:

public ActionResult GetArticle(int id)
{
    var article = db.Articles.Include("Comments").Where(a => a.ArticleID == id).SingleOrDefault();
    return View(article);
}

我理解热切装载的基础,但我的问题是:

  1. 当您从多个相关表中提取数据时,如何实现它?

  2. 将其填充到视图的最佳做法是什么?创建视图模型后,如何填充相关集合?

使用ASP.NET MVC 4(嵌套集合)创建博客评论和回复部分

1)有了多个相关的表,您可以有两种情况:

a) 多个顶级关系:只需添加多个Include语句(我建议使用lambda表达式而不是字符串,以避免拼写错误)。

db.Articles
   .Include(a=>a.Comments)
   .Include(a=>a.SomethingElse)
   .FirstOrDefault(a=>ArticleID==id); // Side note: I would suggest this instead of your Where plus SingleOrDefault

对于这些场景,我总是使用像这样的辅助方法。

b) 多个嵌套的相关实体:

db.Articles
    .Include(a=>a.Comments.Select(c=>c.Remarks)
    .FirstOrDefault(a=>ArticleID==id);

2) 如何将数据传递到视图取决于您自己。我可以告诉你的一个最佳实践是,你不应该让视图懒惰地加载任何依赖的实体或集合。因此,您使用Include是正确的,但我甚至建议删除虚拟(停用延迟加载),以避免意外错过Include。

关于您提到的ViewModels,实际上您使用的不是视图模型,而是数据模型。在大多数情况下,这是可以的,除非您需要以某种方式格式化数据或添加额外信息。然后,您需要创建一个视图模型,并根据来自EF的数据进行映射。

另一种情况是使用WebAPI或Ajax操作。在这种情况下,我建议使用DTO(相当于ViewModel)来更好地控制返回的数据及其序列化。

关于ViewModels的最后一条注释是,如果您有沉重的实体,但只需要几个属性,那么一个好的选择是使用Projections,指示EF只加载所需的属性,而不是完整的对象。

数据库文章.包括(a=>a.注释).选择(a=>new ArticleD to{Id=a.ArticleID,Title=a.Title}).ToListAsync();

这将转换为"SELECT ArticleID,Title FROM Articles",避免返回文章正文和其他您可能不需要的东西。

您可以与Include链接关系。例如:

var article = db.Articles.Include("Comments.Remarks").Where(a => a.ArticleID == id).SingleOrDefault();

不过,我不知道你的第二个问题是什么意思。通过发出此查询,您已经拥有了所有注释以及这些注释的所有注释。因此,您可以访问开箱即用的文章实例:

foreach (var comment in article.Comments)
{
    ...
    foreach (var remark in comment.Remarks)
    {
        ...
    }
}

如何处理视图模型完全取决于您自己。您可以将注释/备注映射到它们自己的视图模型,直接在视图模型上设置它们,等等。这完全取决于您的应用程序的需求,除了您之外,没有人可以对此发表意见。