【问题标题】:Best practise for passing query result to a View?将查询结果传递给视图的最佳实践?
【发布时间】:2015-08-28 12:20:26
【问题描述】:

我是 ASP.NET MVC 的新手,我只是好奇下一个场景的最佳实践是什么。我会将查询结果传递给视图:

public class HomeController : Controller
{
  public ActionResult Index() // show last 3 posts from the database
  {
    DB db = new DB(); // DB is just a tiny wrapper to work with LocalDB sql database
    db.openConnection(ConfigurationManager.ConnectionStrings["PostDBContext"].ConnectionString);      
    db.select(@"select p.id, p.title, p.content, FORMAT(p.created_at, 'yyyy-MM-dd') as created_at, u.firstname,
                                u.lastname, c.name
                       from posts p
                               inner join users u on (u.id = p.created_by)
                               inner join categories c on (c.id = p.category_id)
                       where p.visibility = 'public'
                       order by p.id desc limit 3");

  while( db.read() > 0 ) // reads one row
  {
    ....
  }
  db.closeConnection();
  return View();
}

我已经阅读了几篇关于如何将数据从控制器传递到视图的文章。每篇文章都提到最好和推荐的方法是将数据从模型传递到视图或创建视图模型。所以使用这种方法意味着我需要创建一个 ViewModel 和一个 Model,如下所示:

public class FullPostViewModel
{
  public List<FullPost> Posts { get; set; }
}

public class FullPost
{
  public int id;
  public string title;
  public string content;
  public string created_at;
  public string author_firstname;
  public string author_lastname;
  public string category;
}

然后在控制器中:

....
FullPostViewModel model = new FullPostViewModel();

while( db.read() > 0 ) // reads one row
{
  model.Posts.Add( new FullPost(){id = Convert.ToInt32(db[0]), title = db[1], ....});
}
...
return View(model);

或者最好是创建三个模型:Post、Category、User,然后 FullPost 包含这样的内容:

public class FullPost
{
  public Post p;
  public Category c;
  public User u;
}

例如,如果您有更复杂的查询(3、4、... 连接),这意味着为每个表创建新类。当然,为每个表创建一个类是有意义的,因为这就是 ORM 的全部意义所在。

我只想知道使用模型/视图模型是否始终是显示查询结果的最佳实践(我知道 ViewBag 用于简单和小数据)?在 Laravel (PHP) 中,当涉及到连接的查询时,我经常不使用模型。它只是看起来更容易,但这并不意味着它可以。

【问题讨论】:

  • 您不一定需要FullPostViewModel 模型。您可以将List&lt;FullPost&gt; 传递给视图。
  • 您的第一个代码示例不会向视图发送任何内容。所以我不确定这甚至说明了什么。任何类型都可以用作视图模型,包括查询的结果。当您想要将数据转换为特定于该视图的某些内容或包含特定于该视图的功能时,您需要创建一个自定义视图模型。如果视图只是绑定到后端类型,您可以将后端查询的结果发送给它。
  • @StephenMuecke 感谢您发布关于什么是 mvc 中的视图模型的帖子。
  • @David 我需要将查询结果存储到一些数据结构列表中,... SqlDataReader 用作无缓冲的数据流。必须关闭 SqlDataReader,现在最好在视图中写入逻辑 (SqlDataReader.Close())。至于第一个代码,我只是想展示我正在尝试做的事情(示例查询,......)。

标签: c# asp.net-mvc asp.net-mvc-5


【解决方案1】:

我建议您只传递渲染视图所需的或多或少的数据。由于您可以创建许多视图模型,因此您可以随意将属性放入其中。

例如:

当你想显示一个帖子列表时:return View(List&lt;LightWeightFullPost&gt;) 当您想详细显示帖子时:return View(FullPost)

对于 LightWeightFullPost,您只需发送帖子名称和作者即可。这将使您发送的数据尽可能小,因为您不想在列表视图上显示每个细节。

仅当您真正需要时,才建议在 ViewModel 中传递复杂对象。 例如:在响应 FullPost ViewModel 时,您真的需要完整的 Category 对象吗?还是一个 CategoryId 就够了?

【讨论】:

    【解决方案2】:

    1) 将您的应用程序分层。不要将 SQL 查询放在控制器中,而是在服务层中进行。

    2) 您可以将业务对象返回给 View,但返回 ViewModel 会更好、更灵活。这样您就不需要发送任何不需要的额外字段,并且可以将多个类混合为一个。此外,您可以根据需要在 Controller 中处理格式。

    3) 如果您的视图到处都有逻辑,请再想一想,您可能做错了。尝试使用简单的视图,只处理 HTML 和显示属性。

    根据一条评论,我在下面添加额外信息: 有时您需要格式化小数或 DateTime 属性或将多个属性合并为一个。在控制器中比在视图中更好。假设您需要显示一个金额,包括货币和十进制数字。您可以在视图或控制器中执行此操作。如果您在视图中执行此操作,您将在视图中拥有更多逻辑。然后,如果您对同一页面有不同的视图(例如该页面的移动视图),您需要执行两次或为此创建一个局部视图。如果您在 Controller 中执行此操作,您只需执行一次,您就可以轻松地对其进行测试。

    【讨论】:

    • 我同意关于简单视图的第 3 点。不完全理解 Controller 中的格式化是什么意思。
    • 有时您需要格式化小数或日期时间属性或将多个属性合并为一个。在控制器中比在视图中更好。假设您需要显示一个金额,包括货币和十进制数字。您可以在视图或控制器中执行此操作。如果您在视图中执行此操作,您将在视图中进行更多登录。然后,如果您对同一页面有不同的视图(例如该页面的移动视图),您需要执行两次或为此创建一个局部视图。如果您在 Controller 中执行此操作,您只需执行一次即可轻松测试。
    猜你喜欢
    • 1970-01-01
    • 2013-05-13
    • 2012-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-22
    • 2021-05-01
    • 1970-01-01
    相关资源
    最近更新 更多