使用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)有了多个相关的表,您可以有两种情况:
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)
{
...
}
}
如何处理视图模型完全取决于您自己。您可以将注释/备注映射到它们自己的视图模型,直接在视图模型上设置它们,等等。这完全取决于您的应用程序的需求,除了您之外,没有人可以对此发表意见。