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

时间:2015-11-05 14:02:44

标签: c# asp.net-mvc

好的..我正在建立一个博客评论和回复部分,我将这三个类映射到我的数据库..第一个类包含一篇文章的相关评论的集合..第二个类包含相关评论的集合到评论..

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)将其填充到View中的最佳做法是什么?一旦我创建了一个View Model,我如何填充相关的集合?请举例..

由于

2 个答案:

答案 0 :(得分:2)

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

对于这些场景,我总是使用辅助方法,如this one

b)多个嵌套相关实体:

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

2)您对如何将数据传递给视图有点了解。我可以告诉你的一个最佳实践是,你不应该让视图延迟加载任何依赖实体或集合。因此,您使用Include是正确的,但我甚至建议删除虚拟(停用延迟加载)以避免意外错过包含。

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

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

关于ViewModels的最后一条评论是,如果您有大量实体但只需要一些属性,那么最好选择使用Projections来指示EF只加载所需的属性,而不是整个对象。

db.Articles       .INCLUDE(A =&GT; a.Comments)       .Select(a =&gt; new ArticleDto {Id = a.ArticleID,Title = a.Title})       .ToListAsync();

这将转换为&#34; SELECT ArticleID,Title FROM Articles&#34;,避免返回您可能不需要的文章正文和其他内容。

答案 1 :(得分:1)

您可以将关系与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)
    {
        ...
    }
}

您如何使用视图模型处理完全取决于您。您可以将评论/评论映射到他们自己的模型,直接在视图模型上设置等等。这完全取决于您的应用程序的需求,除了您之外没有人可以说出来。