MusicStore 项目的完整配套视频!
上一次,我们使用了模拟的数据从控制器发送到视图模板。现在,我们开始使用真正的数据库,在这个教程中,我们将指导如何使用 SQL Server Compact 版的数据库,它经常被称为 SQL CE, 来作为数据库引擎,SQL CE 是一个免费的,嵌入式的,基于文件的数据库系统,不需要任何的安装或者配置,很适合本地的开发使用。
注意:可能需要单独安装 SQL Server Compact 4.0 数据库以及 Entity Framework。在我的机器上,这两个软件都是单独安装的。
当然,你还可以使用熟悉的 SQL Server 数据库。
Microsoft SQL Server Compact 4.0
Microsoft SQL Server Compact 4.0 是一种免费的嵌入式数据库,也就是说,你不需要安装数据库系统。软件开发人员可以使用它来构建 ASP.NET 网站和 Windows 桌面应用程序。SQL Server Compact 4.0 的优点是:占用的空间小,支持在应用程序文件夹中专门部署其二进制文件,轻松地使用 Visual Studio 和 WebMatrix 进行应用程序开发,以及无缝地将架构和数据迁移到 SQL Server。
SQL Server Compact 4.0 安装文件的下载地址:http://www.microsoft.com/downloads/zh-cn/details.aspx?familyid=033cfb76-5382-44fb-bc7e-b3c8174832e2&displaylang=zh-cn
不过,你完全可以不使用这个数据库,还继续使用原来的 SQL Server, 在我的机器上,我不能直接使用服务器资源管理器来查看 SQL CE 4 的的数据。如果使用原来的 SQL Server 就不会有这个问题了。
ADO.NET Entity Framework 4.1
EF 4.1有哪些新玩新儿?
1. 首先当然是DbContext API,它是基于以前版本中的ObjectContext和其他一些类型抽象出的一个简单的API,针对常用开发场景和编程模式进行了优化。DbContext可以被于Database First, Model First, Code First三种开发模式。
2. Code First是基于Entity Framework的新的开发模式,原先只有Database First和Model First两种。Code First顾名思义,就是先用C#/VB.NET的类定义好你的领域模型,然后用这些类映射到现有的数据库或者产生新的数据库结构。Code First同样支持通过Data Annotations或fluent API进行定制化配置。
这里的数据访问就使用 Code First 完成,它会使你的数据访问惊人地简单。
关于ADO.NET Entity Framework 4.1,我以前翻译了一个系列,地址: http://www.cnblogs.com/haogj/archive/2011/05/06/2038965.html
ADO.NET Entity Framework 4.1 安装文件下载地址:http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=8363
使用 Entity Framework Code-First 进行数据访问
我们将使用包含在 ASP.NET MVC3 中的 Entity Framework (EF) 支持进行查询和更新数据库中的数据。EF 是一个灵活的进行数据访问的对象关系映射 API,允许开发人员使用面向对象的方式对数据库中的数据进行查询和更新。
Entity Framework 4 支持一种称为代码优先的开发模式,代码有限允许你通过编写简单的类来创建模型对象(也被称为 POCO, 简单的,老的 CLR 对象),然后通过类来创建数据。
注意,需要在你的项目中引用程序集 EntityFramework,在你安装 Entity Framework 的文件夹中可以找到这个程序集。
修改我们的模型类
我们将延后数据库的创建工作,在完成这个任务之前,我们先修改我们得模型类,增加我们需要的内容。
增加艺术家 Artist 类
我们的专辑将要关联到艺术家,所以,我们需要增加一个简单的类来描述艺术家,增加一个新的名为 Artist 的类。
namespace MvcMusicStore.Models
{
public class Artist
{
public int ArtistId { get; set; }
public string Name { get; set; }
}
}
更新现有的模型类
namespace MvcMusicStore.Models
{
public class Album
{
public int AlbumId { get; set; }
public int GenreId { get; set; }
public int ArtistId { get; set; }
public string Title { get; set; }
public decimal Price { get; set; }
public string AlbumArtUrl { get; set; }
public Genre Genre { get; set; }
public Artist Artist { get; set; }
}
}
然后更新 Genre 类
namespace MvcMusicStore.Models
{
public class Genre
{
public int GenreId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public List<Album> Albums { get; set; }
}
}
增加 App_Data 文件夹
这一步并不必要,如果使用 SQL CE4,可以用来保存数据库文件,如果使用 SQL Server 则不一定需要。
我们在项目中增加 App_Data 文件夹用来保存数据库文件,App_Data 是一个 ASP.NET 中特殊的文件夹,已经被网站对其中数据地访问进行了安全限制,从项目的菜单中,选择增加 ASP.NET 文件夹,然后,选择 App_Data.
在 Web.config 中创建数据库连接串
我们需要在网站的配置文件中增加一些行,以便 Entity Framework 知道如何连接到我们的数据库,双击 Web.config 文件。
卷到文件的最后,然后增加一个 <connectionStrings> 的配置节,如何所示:
<connectionStrings>
<add name="MusicStoreEntities"
connectionString="Data Source=|DataDirectory|MvcMusicStore.sdf"
providerName="System.Data.SqlServerCe.4.0"/>
</connectionStrings>
注意,这里数据库连接串的名称很重要,以后使用 EF Code-First 的时候,通过它来找到数据库,这里的链接串种使用了 Data Source=|DataDirectory|MvcMusicStore.sdf,这里的 DataDirectory 指的就是项目中的 App_Data 文件夹夹。
如果使用 SQL Server, 可以使用如下的链接串。注意 providerName 也要替换成 SQLServer 使用的提供器。
<!-- 数据库连接串的配置 -->
<connectionStrings>
<add name="MusicStoreEntities"
connectionString="server=.\sqlexpress;database=musicstore;integrated security=true;"
providerName="System.Data.SqlClient"/>
</connectionStrings>
增加上下文类
在模型文件夹上右键点击,然后,增加一个新的名为 MusicStoreEntities.cs 的文件。 需要注意的是,这个类的名称必须与数据库连接串的名称一致。
这个类将反映 Entity Framework 数据库的上下文,用来处理创建,读取,更新和删除的操作,代码如下所示:
using System.Data.Entity;
namespace MvcMusicStore.Models
{
public class MusicStoreEntities:
DbContext
{
public DbSet<Album> Albums { get; set; }
public DbSet<Genre> Genres { get; set; }
public DbSet<Artist> Artists { get; set; }
}
}
注意,这里使用了 System.Data.Entity 命名空间。记得要 using 一下。
不需要其他的配置,特定的接口等等,通过扩展 DbContext 基类,我们得 MusicStoreEntities 类就可以处理我们对数据库的操作了,现在,我们就开始,先为我们的类增加一些属性来从数据库获取额外的信息。
增加我们的商店分类数据
对于 Code First 来说,我们首先定义模型,然后通过模型来创建数据库,甚至也不需要写 Insert 语句,我们可以通过标准的 C# 代码来创建表中的记录。
我们先通过一些种子数据通过 Entity Framework 为新创建的数据库增加一些数据。先创建我们的商店分类,这需要通过一个 Genres 的列表完成,还有专辑。在 MvcMusicStore-Asset.zip 文件中,已经包含了用来简单地创建数据的文件,有一个保存在 Code 文件夹中的类来完成。
在 Code 中的 Models 文件夹中,找到 SampleData.cs 文件,将它加入到 Models 文件夹中,如下所示。
现在,我们需要增加一些代码来告诉 Entity Framework 关于 SampleData 类的事情。双击 Global.asax 文件,打开它,在 Application_Start 方法中,增加如下的行。
// 一般用来进行网站的初始化
protected void Application_Start()
{
System.Data.Entity.Database.SetInitializer(new MvcMusicStore.Models.SampleData());
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
这个方法用来初始化数据库,然后填充一些数据。
这样,我们就完成了配置 Entity Framework 的工作。
查询数据库
现在,我们更新一下我们的 StoreController 以便取代以前模拟的数据,通过调用我们的数据库来查询实际数据。我们先在 StoreController 中定义一个字段来访问我们的 MusicStoreEneities 类的对象实例,它命名为 storeDB。
using MvcMusicStore.Models;
namespace MvcMusicStore.Controllers
{
public class StoreController : Controller
{
MusicStoreEntities storeDB = new MusicStoreEntities();
更新 Index Action 查询数据库
MusicStoreEntities 类通过 Entity Framework 提供了数据库中数据表的集合,更新一下 StoreController 的 Index Action 方法来获取全部的分类数据。我们原来使用硬编码的数据,现在,我们可以使用 Entity Framework 的 Generes 集合来取代它了。
对于 EF 的使用,我建议你了解一下 Repository 模式。
//
// GET: /Store/
public ActionResult Index()
{
var genres = storeDB.Genres.ToList();
return this.View( genres );
}
对于视图模板不需要任何修改,我们仍然返回同样的 StoreIndexViewModel 。
运行程序,访问 /Store 地址的时候,我们现在可以看到数据库中分类的列表。
使用数据库中的数据更新浏览和明细页面
当在首页通过 /Store/Browse?genre=[some-genre] 链接访问 Browse 这个 Action 的时候,我们需要通过流派的名称来获取相应的专辑,对于我们的音乐店来说,每个流派的名称是唯一的,可以通过 LINQ 中的 Single 扩展方法来获取查询结果中的唯一的流派对象。
var example = storeDB.Genres.Single(g => g.Name == “Disco”);
Single 方法使用一个 Lambda 表达式作为参数,表示我们希望获取匹配指定值的单个流派对象,在上面的例子中,我们将会获得名为 Disco 的流派对象。
通过 EF ,在获得流派对象的同时,我们还可以获取流派相关的对象,例如属于这个流派的专辑集合,我们可以提前获取相关的专辑信息,这就需要我们修改一下上面的查询,包含专辑信息。通过 Include 方法可以指定我们希望获取的相关信息,这种方式非常有效,这样,我们就可以在一次数据访问中,既可以获取流派对象,也可以同时获取相关的专辑对象。
这样更新之后,我们的 Action 方法将会成为下面的样子。
// /Store/Browse?genre=DISCO
public ActionResult Browse( string genre )
{
var genreModel = storeDB.Genres.Include("Albums").Single(g => g.Name == genre);
return this.View(genreModel);
}
注意,在流派 Genre 的属性中有一个名为 Albums 的集合属性。
然后,我们可以更新一下 Store 的 Browse 视图来显示相应的专辑,打开视图模板,增加一个列表。
@model MvcMusicStore.Models.Genre
@{
ViewBag.Title = "Browse";
}
<h2>
Browsing Genre: @Model.Name</h2>
<ul>
@foreach (var album in Model.Albums)
{
<li>
@album.Title
</li>
}
</ul>
运行程序,浏览 /Store/Browse?genre=Jazz,现在就可以看到保存在数据库中的的专辑数据了。
同样,我们还可以修改一下 Details ,通过传递的参数来获取专辑对象。修改后的方法如下所示。
// /Store/Details/5
public ActionResult Details(int id)
{
var album = storeDB.Albums.Find(id);
return View(album);
}
运行程序,访问 /Store/Details/1,应该可以看到下面的内容。
我们更新一下 Browse 视图,提供链接到明细页面的超级链接,这里,我们使用 ActionLink 方法,修改后的视图如下所示。
再次浏览 Browse 的时候,每个专辑应该已经成为了一个链接,如图所示: