ASP.NET MVC 3.0 Razor视图如何展示多实体
Razor视图模型支持@model来初始化页面对象类型,比如:
1 @model FlashTravel.Models.Traveller>
也可以是一个支持迭代的公开枚举器:
1 @model IEnumerable<FlashTravel.Models.Traveller>
当我们只关注对一个实体类进行呈现时,MVC 3.0的实现非常给力,Controller层只需要两行代码:
public ActionResult Index()
{
var traveller = dbFlashTravel.Traveller.ToList();
return View(traveller);
}
ToList()方法返回的是List<T>集合,它实现(Implements)了接口IEnumerable<out T>,所以var型变量traveller被传递到View层时,可采用foreach进行遍历:
@foreach (var item in Model) {
//......
}
再强大的框架,也只是把简单的事变得更简单,而问题一旦稍变复杂,多半都要靠聪明的大脑来解决,我挺喜欢去42区逛,其首页的类似微博的即时信息功能挺有意思;好歹自己也是做BS开发的,于是就采用MVC 3.0模拟一个玩玩。
其业务模型大概可以这样描述:已登录会员可以发表一条碎碎念(文字限定142),与之相随的图片数量不限定(测试时只提供一张),同时可以被别的会员回复。从该描述中提取出最基本的实体对象:会员(Traveller)、碎碎念(Chat)、碎碎念图片(ChatImage)、碎碎念回复(ChatReply)
来自VS2010的免费图片:
很明显,实体Chat的主键字段ChatID关联起了实体ChatImage(1对多)和实体ChatReply(1对多)。
Linq to SQL该ORM框架会自动把数据库表一一映射为同名实体类(EF4.0道理亦然),这些实体类就像筑造楼房的砖瓦一样,成为各种业务模型组装的最为基本的对象。基于上述分析,显然发表碎碎念这一业务模型有三个最基本的实体类参与:Chat、ChatImage、ChatReply,为了更好地表述他们,我将该业务模型命名为ChatIntegration(碎碎念综合),并采用一个视图模型模式(ViewModel Pattern)类来进行封装:
namespace FlashTravel.ViewModels
{
/// <summary>
/// 碎碎念综合
/// </summary>
public class ChatIntegration
{
/// <summary>
/// 碎碎念
/// </summary>
public Chat ChatHeader { set; get; }
/// <summary>
/// 碎碎念图片
/// </summary>
public IList<ChatImage> ChatImages { set; get; }
/// <summary>
/// 碎碎念回复
/// </summary>
public IList<ChatReply> ChatReplys { set; get; }
}
}
上述代码表明,单个碎碎念业务模型包含着一个碎碎念主体叫ChatHeader,和若干图片(复数),以及若干回复(复数)。
一般来讲,Model层在项目中往往就是起到一个承上启下的作用(MVC或传统的三层),如同小学时老师教我们八股式的写作文一般:先开头,接着铺述一段,然后作一个承上启下的段落,随之进入下一段的描写,最后以一个总结段结尾。这里的业务模型(ChatIntegration)同理:第一段,在Controller层先捞取数据库中的数据(基于Linq to SQL)将其存储在业务模型中;第二段,业务模型将被抛给View层的页面,通过Razor引擎遍历呈现。
如前所述,接下来会做两件事:先往下层看,瞧一下处于中间的业务模型(ChatIntegration)是如何得到数据库数据;然后再抬头仰视,看看业务模型(ChatIntegration)被抛给View后如何遍历数据。
(一.)往下层看,按MVC 3.0的"分离关注点"思想,对于访问数据库的代码应该采用Repository设计模式,使得Controller层中的Action仅需调用Repository层中的相关函数就可得到数据集,从而很顺畅地将函数返回值传给View层,虽然"约定大于配置"很重要,但只要我的精简尚未破坏MVC架构,姑且就"耦合"一下吧,我会把访问数据库的代码直接写在名为Index的Action中:
public class ChatController : Controller
{
FlashTravelDataContext dbFlashTravel = new FlashTravelDataContext();
public ActionResult Index()
{
//查询所有碎碎念
var chatIntegrationList = from chat in dbFlashTravel.Chat
join chatImage in dbFlashTravel.ChatImage
on chat.ChatID equals chatImage.ChatID into chatImages
join chatReply in dbFlashTravel.ChatReply
on chat.ChatID equals chatReply.ChatID into chatReplys
select new ChatIntegration
{
ChatHeader = chat,
&nbs
补充:Web开发 , ASP.Net ,