免费下载案例集|20+数字化领先企业人才培养实践经验 了解详情
写点什么

使用 Northwind 和 Entity 框架的 ASP.NET MVC 实例发布

  • 2008-02-23
  • 本文字数:5890 字

    阅读完需:约 19 分钟

近日,作为 ASP.NET 3.5 Extensions 预览版组成部分的微软 ASP.NET MVC 框架发布了 CTP 版本。自此,MVC 框架就吸引了众多业界人士的眼球,并纷纷在博客以及各个开发者所关注的网站上进行了介绍。

微软 CLR 和.NET 框架团队的成员 Brad Abrams 发布了一个非常优秀的实例,为开发者展示了如何有效地使用微软 MVC 框架中的某些最新工具。该实例源于 Scott Guthrie 的 MVC 实例,Scott 将这些内容放在他的博客上,演示了在最初形式下的 MVC 框架是如何进行工作的。Scott 的实例采用循序渐进的方式将其编写为四部分内容:

MVC 框架为开发者提供了足够的灵活性去选择视图与模型引擎以满足他们的需要。在 Scott 的示例中,他使用了 LINQ to SQL 模型,但 Brad 决定使用 Entity 框架,并以 Northwind 数据库作为数据源。

开发者可以选择多种不同的模型提供者,例如:

在将来,我们或许还可以看到其他的模型提供者:

Brad 的方法是创建一个实例,引导开发者如何使用 ASP.NET MVC Application and Test 创建项目。开发者需要安装下列内容:

指南

该指南内容广泛,有很高的学习价值,从中可以获知 MVC 框架的功能以及如何将它们联系在一起。使用 MVC 不同于以往所开发的 Web Forms 应用程序,甚至对于经验丰富的 ASP.NET Web Form 开发人员来说,也需要逐渐地习惯它。

入门

一旦 ASP.NET 3.5 Extensions 安装完毕,就有几种项目类型可供选择,其中包括 ASP.NET MVC Web Application 以及 ASP.NET MVC Web Application and Test。ASP.NET MVC 被设计为易于测试的框架,而 Brad 也使用了测试功能。

File/ 新建项目 - 选择 ASP.NET MVC Web Application and Test

image

它会创建一个单独的解决方案,包括一个 Web 应用程序项目,并且,该项目可以用做单元测试。它们都是预先生成的,包含了你需要创建的一些基础内容。

创建 Routes

MVC 框架中的 Routing(路径选择)是设计中非常值得关注的一项功能。开发人员可以通过它判断应用程序如何查找页面。在经典的 ASP.NET 应用程序中,一个页面例如 home.aspx,总会有一个非常清晰的路径可以访问该页面,通常形如 www.mywebsite.com/home.aspx。与此比较,Routing 为开发者提供了更多的灵活性。

ASP.NET MVC 提供的其中一个非常强大的新特性是它能够定制访问应用程序的 URLs。显然,对于磁盘上的物理文件和用来访问页面功能的 URL 而言,URL 路径选择特性隔离了两者之间的关联关系。这对于搜索引擎的优化以及提高网站的通用性都是非常重要的。例如,现在我们不需要访问这样的地址 http://localhost/Products/ItemDetails.aspx?item=42,而是通过 http://localhost/Products/CodFishOil 进行访问,这样的 URL 更让人赏心悦目。

它的实现是在 MVC 应用程序的 global.asax 文件中创建一个路径表。值得庆幸的是,模板中的默认内容对于应用程序而言已经足够了。

RouteTable.Routes.Add(new Route<br></br>{<br></br> Url = "[controller]/[action]/[id]",<br></br> Defaults = new { action = "Index", id = (string)null },<br></br> RouteHandler = typeof(MvcRouteHandler)<br></br>});这段代码给出了我们针对自己的站点所需要的 URLs 格式。特别的,格式为

http://localhost/Products/Details/CodFishOil

的 URL 应该转换为 ProductsController 类(注意,我们为类名添加了“Controller”后缀,使得这些类能够区别于设计中的模型对象)。接着,Action 是 Details 类的方法,最后,传递给 details 方法的参数为 CodFishOil。

当然,还可能有其它的格式,只需要在 URL 格式的字符串中修改正则表达式即可。

创建模型(Model)

模型是大多数 web 应用程序的心脏,几乎所有的数据都存储在模型之中。MVC 框架允许开发者几乎没有限制地使用任意一种数据源,并能够轻松地在各种数据源之间进行切换。

模型表示你将要在应用程序中使用的数据。在本例中,从模型开始应用程序的核心开发是一个不错的选择。

将 Northwind.mdf 文件复制到 MVCApplication 的 App_Data 文件夹中。对于 SqlServer 而言,Northwind 可能是最常用的示例数据库了。你可以从官方地址 中下载它,如果您只需要原始文件的话也可以从这里获取

image

接下来,我们需要基于 northwind 数据库创建 LINQ 模型,以便于进行操作。你可以使用 NHibernate LinqToSql Entity 框架 ,或者其它的.NET ORM 技术。只要它的返回结果为.NET 对象,ASP.NET MVC 框架就能够对其进行操作。在本例中,我使用了 Entity 框架。

右键单击 Models 目录,选择 add new item

image

在对话框中,选择 ADO.NET Entity Data Model。

在向导中,选择“Generate from Database”,然后赋予默认的“Northwnd”连接字符串。

对于演示而言,我们只需要使用 Categories、Products 和 Supplier 数据表,当然,你也可以扩展该演示以引入更多丰富的特性集。但是目前除了这三者之外,不要选择数据库视图、存储过程和其他的数据表。

image

当你单击完成时,VS 会创建一组.NET 类,这些类定制创建了访问数据库的相关内容。我们还能够获得一个界面友好的设计器,以可视化方式展现数据之间的关系。

image

注意,赋予这些类的默认名仍然沿用了数据库的复数名词,但是在我们的 OR 映射中,它们表达的是单个的实例。为了使得代码具有可读性,应该将所有的表名修改为准确的单数名词:Category、Product 和 Supplier。至于 Product 的 Navigation 属性,也需要修改为单数形式,因为对于产品而言,只有一个类别(Category)和供应商(Suppler)。

image

接下来,我们需要修改命名空间使得代码更加准确直观……右击设计视图,设置相关的属性,例如将 namespace 设置为“NorthwindModels”,将 Entity Container 的名称设置为“NorthWindEntities”

image

虽然我们没有给出模型的完整示例,但给出的内容已经足以指导开发者完成剩余的内容……让我们跳转到下一个话题,来看一看控制器。

创建控制器

控制器是我们应用程序的大脑。我们可以将控制器想象为机场的空中交通控制器,指挥飞机的进出方向。一方面,控制器负责获取数据,另一方面,它则负责将数据传递到视图。

右击 Controller 目录,选择“Add new Item”。在对话框中找到 MVC Controller,并确保赋予的名称是以 Controller 后缀结尾的。在我们的例子中将会编写 ProductsController 类。

image

好的,我们现在从 ProductsController.cs 开始

控制器的目的是为视图准备模型对象。我们希望尽可能地将逻辑放到视图之外,因为它很难在视图中进行测试。因此,在控制器中,我们会访问模型,并获得所有创建完毕的模型,这样,所有视图所要做的就是输出某些数据。

首先,我们需要访问数据库。

1. 添加正确的命名空间,包括 Linq 以及指向我们的 OR 映射的引用。

using System.Linq;<br></br>using NorthwindModel;2、接下来,我们需要创建 NorthwindEntities 容器类的实例。几乎所有的 action 都会访问这个类。

public class ProductsController : Controller<br></br>{<br></br> NorthwindEntities Northwind = new NorthwindEntities();好的,现在我们需要创建第一个 action:显示所有的类别。记住,控制器的职责是为视图准备模型对象。在定义一个新的 action 时,我喜欢首先编写一条注释,以提醒我访问这一功能的 URL 是什么。

接下来要做的事情就是从模型中访问 Categories。我将结果放到一个泛型集合类中(你可能需要添加 System.Collections.Generic 引用),然后将结果传递到名为“Categories”的视图中。这是一个非常简单的例子,后面我们会在此处添加更加复杂的逻辑。

//URL: http://localhost/Products/Categories<br></br>[ControllerAction]<br></br>public void Categories()<br></br>{<br></br> List categories = Northwind.Categories.ToList();<br></br> RenderView("Categories", categories);<br></br>}下一步,我们需要创建“Categories”视图。

创建视图

对于视图而言,MVC 框架给了开发者和模型差不多的灵活性。开发人员可以选择一组视图引擎并对它们进行切换。

右击 Views 文件夹,添加新的目录“Products”。这使得我们可以清晰地组织我们的视图。右击 Views/Products 文件夹,然后添加一个新项 MVC View Content Page。我们会充分地利用 Master Page,它是在默认的项目中已生成的,可以使得界面看起来更加友好。

image

将该页面命名为 Categories.aspx。视图的名称非常重要,它必须与之前提及的 RenderView 方法的第一个参数相匹配。

默认项目会将 Master Page 放到 Views/Shared/Site.Master 中

image

ViewData 是我们要从控制器中传递的内容,为了得到对它的强类型访问,我们需要告知视图页面它所期待的类型。这可以通过打开 codebehind 文件(Categories.aspx.cs),修改继承的类型来完成:

public partial class Categories : ViewPage<br></br>{<br></br>}<br></br> 修改为: public partial class Categories : ViewPage< List > <br></br>{<br></br>}接着你就可以编写清晰、简单、可设计的 HTML 了。注意,我在这里将所有从 ViewData 返回的元素项进行了一次循环,然后将它们作为链表传出。我使用了 MVC 的辅助方法 Html.ActionLink,为包含了对应产品 ID 的 List action 创建了 URL。

<% foreach (var category in ViewData) { %><br></br> <%= Html.ActionLink(category.CategoryName, new { action="List", id=category.CategoryName }) %><br></br><% } %>## 浏览产品

好的,一切准备妥当,可以运行了。

按下 F5,导航条上就会出现我们刚才编写的控制器 action: http://localhost:64701/products/Categories

image

点击任何一个链接都会出现一个错误,因为我们还没有编写 List action。这是我们接下来所要做的。

说句题外话,如果你像我这样习惯在开发的 aspx 页面上使用“View in Browser”,你可能会看到这个错误。

若要重现此错误,请右击 Categories.aspx,然后选择 View in browser。

image

你会获得一个错误。为什么?是的,请务必谨记在 MVC 模型中,所有的执行都要经过控制器,视图自身是不能运行的。未来的工具会对此进行改进,但至少在现在,可以对 default.aspx 使用 F5 或者通过“run in browser”进行操作。当然应该首先确保你已经编译了解决方案。

List Action 视图

现在,让我们回到之前省略的内容:添加 List action。在这里我们需要的是在给定的 Category 中查找所有的产品。首先,我需要从模型中获取所有产品,然后我必须确保 Category 的引用已经被加载。Entity 框架在默认情况下提供了一个显式的加载模型。因此,你必须明确地加载你所需要的所有表。最后,我们再呈现视图。

//example URL:http://localhost:64701/products/List/Confections<br></br>[ControllerAction]<br></br>public void List(string id)<br></br>{<br></br> List products = Northwind.GetProductsByCategory(id);<p> //prepare the view by explicitly loading the categories </p><br></br> products.FindAll(p => p.Category == null).ForEach(p => p.CategoryReference.Load());<p> RenderView("ListingByCategory", products);</p><br></br>}注意,我调用了 NorthwindDataContext 类的一个自定义方法。我个人倾向于将所有的数据访问逻辑封装到这个类中。若要定义该方法,可以右击 Model,通过 add new item 选择 CodeFile,并命名为 NorthwindDataContext.cs,然后给出如下的实现。

using System;<br></br>using System.Collections.Generic;<br></br>using System.Linq;<p>namespace NorthwindModel</p><br></br>{<br></br> public partial class NorthwindEntities<br></br> {<br></br> }<br></br>}现在,你可以很容易地为该类添加数据访问方法了,例如我们之前使用的 GetProductsByCategory() 方法。

public List GetProductsByCategory(string category)<br></br>{<br></br> return Products.Where(p => p.Category.CategoryName == category).ToList();<br></br>}<br></br>下一步,我们需要添加 ListingByCategory 视图。遵循前面介绍的相同步骤,我们在 Views/Products/ 目录下添加 ListingByCategory.aspx 页面。

这一次,我们应该让 ViewData 成为 List 类型

public partial class ListingByCategory : ViewPage<list><br></br>{<br></br>}</list>接下来实现视图,我们只是对视图的数据进行了循环,并以正确的格式输出。

<%--Print out the catagory name--%> <br></br><% foreach (var product in ViewData) { %><br></br> <% if (product.Category.CategoryName != null) { %> <br></br> <%=product.Category.CategoryName %><br></br> <% break; %><br></br> <%} //end if %><br></br><%}//end foreach %><br></br><% foreach (var product in ViewData) { %><br></br> <img alt="<%=product.ProductName %>" src="/Content/Images/<%=product.ProductID%>.jpg" /><br></br> <%=product.ProductName %> <br></br> Price: <%=String.Format("{0:C2}", product.UnitPrice)%> <br></br><% } %>一旦你在实例项目中添加了 /Content/Images 目录,就会获得如下页面:

image

Brad 的实例是用 C#编写的,因此 Julie Lerman 选择创建了和 Brad 相似的例子,她使用了 VB.NET 和 AdventureWorksLT 数据库 ,并重点关注了更多高效的 Entity 框架查询。Julie 指出了她的实现与 Brad 的重大不同之处。

  • 我的 EDM(译者注:指实体数据模型)创建自 AdventureWorksLT 数据库。
  • 在 AW(译者注:AdventureWorksLT 的简写)中,SalesOrderHeaders 和 Customer 的关系与 Northwind 中 Products 和 Category 的关系相同。因此,在他使用 Products 的地方,我使用 SalesOrderHeaders;在他使用 Categories 的地方,我使用 Customers。
  • 若要轻易地获取数据并将其传给视图,则其中一个关键是我们需要传递“一个”对象(而且不是匿名类型)到视图。然而,对于 Order 列表(每一个都具有 Customer 的名字)和 Details 列表(每一个都具有从 Order 和 Customer 中获得的数据)而言,我们真正需要的是一个对象图。

那些希望下载完整的应用程序,而不希望循序渐进地了解实现过程的开发人员可以从 Brad 的博客中下载能够直接运行的实例

查看英文原文: ASP.NET MVC Example with Northwind and Entity Framework Published

2008-02-23 00:595062
用户头像

发布了 109 篇内容, 共 40.8 次阅读, 收获喜欢 14 次。

关注

评论

发布
暂无评论
发现更多内容

纸币会消失吗:数字货币如何走进我们生活

CECBC

货币

域名和服务器的购买和配置

空城机

阿里云 轻量级服务器 云翼计划

面试拜佛保过?圈内罕见阿里面试官手册,2021最强面试笔记非它莫属

Java 程序员 架构 面试

Three.js杂记(十一)—— 精灵与粒子(绘制中国地图)

空城机

大前端 WebGL 3D渲染 3D可视化 three.js

moviepy音视频剪辑:视频剪辑基类VideoClip的属性及方法详解

老猿Python

Python 编程语言 音视频 Moviepy

js逐步教你实现原生古诗匹配系统(html逻辑 css逻辑 js逻辑)

js

DCGM:监控Kubernetes集群的GPU资源

DCOS

kubernetest

moviepy音视频剪辑:moviepy中的剪辑基类Clip的属性和方法详解

老猿Python

Three.js杂记(十一)—— 精灵与粒子(绘制中国地图)

空城机

大前端 WebGL 3D渲染 3D可视化 three.js

《Redis 核心技术与实战》学习笔记 07

escray

redis 学习 极客时间 3月日更 Redis 核心技术与实战

Three.js杂记(六)——3D模型

空城机

大前端 WebGL 3D模型 3D可视化 three.js

Three.js杂记(十)——贴图

空城机

大前端 WebGL 3D渲染 3D可视化 three.js

Wireshark数据包分析学习笔记Day19

穿过生命散发芬芳

Wireshark 数据包分析 3月日更

区块链下乡

CECBC

区块链

时间复杂度总结

我是程序员小贱

3月日更

2021春招Java后端开发面试总结:25个技术专题(最全面试攻略)

比伯

Java 编程 架构 面试 程序人生

工程方法事例实战

风翱

软件工程 3月日更

「产品经理训练营」作业 06:用户路径地图与漏斗模型

狷介

产品经理训练营

渣硕试水字节跳动,本以为简历都过不了,123+HR面直接拿到意向书

Java 程序员 架构 面试

Three.js杂记(五)——坐标轴、光源

空城机

大前端 WebGL 3D渲染 3D可视化 three.js

Three.js杂记(九)—— 练习:地球

空城机

大前端 WebGL 3D可视化 three.js

去了解一下区块链

空城机

区块链 笔记 区块链发展

moviepy简介及安装

老猿Python

Python 编程语言 音视频 Moviepy PyQt

教你如何用霍夫变换完成扭曲车牌识别

程序媛观澜

机器学习 图像识别

Three.js杂记(七)—— 全景效果制作·上(含python爬虫偷碎图,canvas重组图片)

空城机

大前端 WebGL 3D渲染 3D可视化 three.js

Three.js杂记(八)—— 文本几何体

空城机

大前端 WebGL 3D渲染 3D可视化 three.js

如何减少加班导致的离职?

石云升

项目管理 28天写作 职场经验 管理经验 3月日更

Python-计算机视觉-OpenCV-video

Aldeo

Python OpenCV Video

开启Python学习之旅,分享学习路上的神器集合!

王小王-123

Python 学习 资源分享 工具分享

JS逐步教你做(自己版本)的视频播放器(html逻辑 css逻辑 js逻辑)

js

从一道美团春招笔试题目出发,揭开树DP的神秘面纱

面鲸

面试 数据结构与算法 笔试题

使用Northwind和Entity框架的ASP.NET MVC实例发布_.NET_Robert Bazinet_InfoQ精选文章