使用 LINQ to SQL 创建模型类 (VB)

Microsoft

下载 PDF

本教程的目的是说明为 ASP.NET MVC 应用程序创建模型类的一种方法。 本教程介绍如何利用 Microsoft LINQ to SQL 生成模型类和执行数据库访问。

本教程的目的是说明为 ASP.NET MVC 应用程序创建模型类的一种方法。 本教程介绍如何利用 Microsoft LINQ to SQL 生成模型类和执行数据库访问。

在本教程中,我们将生成一个基本的 Movie 数据库应用程序。 我们首先以最快、最简单的方式创建 Movie 数据库应用程序。 我们直接从控制器操作执行所有数据访问。

接下来,了解如何使用存储库模式。 使用存储库模式需要更多的工作。 但是,采用此模式的优点是,它使你能够生成能够适应更改且易于测试的应用程序。

什么是模型类?

MVC 模型包含 MVC 视图或 MVC 控制器中不包含的所有应用程序逻辑。 具体而言,MVC 模型包含所有应用程序业务和数据访问逻辑。

可以使用各种不同的技术来实现数据访问逻辑。 例如,可以使用 Microsoft Entity Framework、NHibernate、Subsonic 或 ADO.NET 类生成数据访问类。

在本教程中,我使用 LINQ to SQL 来查询和更新数据库。 LINQ to SQL 提供了一种与 Microsoft SQL Server 数据库进行交互的非常简单的方法。 但是,请务必了解,ASP.NET MVC 框架未以任何方式绑定到 LINQ to SQL。 ASP.NET MVC 与任何数据访问技术兼容。

创建电影数据库

在本教程中,为了说明如何生成模型类,我们将生成一个简单的 Movie 数据库应用程序。 第一步是创建新数据库。 右键单击解决方案资源管理器窗口中App_Data文件夹,然后选择菜单选项“添加”、“新建项”。 选择SQL Server数据库模板,为其命名为 MoviesDB.mdf,然后单击“添加”按钮 (请参阅图 1) 。

添加新SQL Server数据库

图 01:添加新SQL Server数据库 (单击以查看全尺寸图像)

创建新数据库后,可以通过双击 App_Data 文件夹中的 MoviesDB.mdf 文件打开数据库。 双击 MoviesDB.mdf 文件将打开服务器资源管理器窗口, (请参阅图 2) 。

使用 Visual Web Developer 时,“服务器资源管理器”窗口称为“数据库资源管理器”窗口。

“服务器资源管理器”窗口的屏幕截图,其中显示了“表”文件夹在文件夹层次结构中突出显示。

图 02:使用“服务器资源管理器”窗口 (单击以查看全尺寸图像)

我们需要向数据库添加一个表示电影的表。 右键单击“表”文件夹,然后选择菜单选项 “添加新表”。 选择此菜单选项将打开表Designer (请参阅图 3) 。

Microsoft Visual Studio 窗口的屏幕截图,其中显示了“表Designer”功能。

图 03:表Designer (单击以查看全尺寸图像)

我们需要将以下列添加到数据库表:

列名称 数据类型 允许 Null 值
ID int False
标题 Nvarchar (200) False
导演 Nvarchar (50) False

需要对 Id 列执行两项特殊操作。 首先,需要通过选择表Designer中的列并单击键的图标,将 Id 列标记为主键列。 LINQ to SQL 要求在对数据库执行插入或更新时指定主键列。

接下来,需要通过将值 Yes 分配给 Is Identity 属性,将 Id 列标记为 Identity 列, (请参阅图 3) 。 “标识”列是一个列,每当向表添加新的数据行时,都会自动为其分配一个新编号。

进行这些更改后,请保存名为 tblMovie 的表。 可以通过单击“保存”按钮保存表。

创建 LINQ to SQL 类

MVC 模型将包含表示 tblMovie 数据库表的 LINQ to SQL 类。 创建这些 LINQ to SQL 类的最简单方法是右键单击 Models 文件夹,选择 “添加”,选择“新建项”,选择 LINQ to SQL 类模板,为类命名为 Movie.dbml,然后单击“ 添加 ”按钮 (见图 4) 。

创建 LINQ to SQL 类

图 04:创建 LINQ to SQL 类 (单击以查看全尺寸图像)

创建 Movie LINQ to SQL 类后,立即显示对象关系Designer。 可以将数据库表从“服务器资源管理器”窗口拖到“对象关系Designer,以创建表示特定数据库表的 LINQ to SQL 类。 我们需要将 tblMovie 数据库表添加到对象关系Designer (请参阅图 4) 。

使用对象关系Designer

图 05:使用对象关系Designer (单击以查看全尺寸图像)

默认情况下,对象关系Designer创建一个类,该类的名称与拖到Designer上的数据库表名称完全相同。 但是,我们不想将类称为 tblMovie。 因此,请单击Designer类的名称,并将类的名称更改为 Movie。

最后,请记住单击“ 保存 ”按钮 (软盘) 的图片,以保存 LINQ to SQL 类。 否则,LINQ to SQL 类不会由对象关系Designer生成。

在控制器操作中使用 LINQ to SQL

有了 LINQ to SQL 类后,就可以使用这些类从数据库中检索数据了。 本部分介绍如何直接在控制器操作中使用 LINQ to SQL 类。 我们将在 MVC 视图中显示 tblMovies 数据库表中的电影列表。

首先,我们需要修改 HomeController 类。 可以在应用程序的 Controllers 文件夹中找到此类。 修改 类,使其看起来像清单 1 中的类。

清单 1 - Controllers\HomeController.vb

<HandleError()> _
Public Class HomeController

     Inherits System.Web.Mvc.Controller

     Function Index()
          Dim dataContext As New MovieDataContext()
          Dim movies = From m In dataContext.Movies _
               Select m
          return View(movies)
     End Function
End Class

列表 1 中的 Index () 操作使用 LINQ to SQL DataContext 类 (MovieDataContext) 来表示 MoviesDB 数据库。 MoveDataContext 类由 Visual Studio 对象关系Designer生成。

针对 DataContext 执行 LINQ 查询,以从 tblMovies 数据库表检索所有电影。 电影列表分配给名为 movies 的局部变量。 最后,电影列表通过视图数据传递到视图。

为了显示电影,接下来需要修改“索引”视图。 可以在 Views\Home\ 文件夹中找到索引视图。 更新索引视图,使其看起来像清单 2 中的视图。

清单 2 - Views\Home\Index.aspx

<%@ Page Language="VB" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="false" CodeBehind="Index.aspx.vb" Inherits="MvcApplication1.Index" %>
<%@ Import Namespace="MvcApplication1" %>
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">

<ul>
<%  For Each m As Movie In ViewData.Model%>
    <li><%= m.Title %></li>
<% Next%>
</ul>
</asp:Content>

请注意,修改后的索引视图在视图顶部包含 % <@ import namespace %> 指令。 此指令导入 MvcApplication1 命名空间。 我们需要此命名空间才能在视图中使用模型类(尤其是 Movie 类)。

清单 2 中的视图包含一个 For Each 循环,循环访问 ViewData.Model 属性表示的所有项。 将显示每个电影的 Title 属性的值。

请注意,ViewData.Model 属性的值将强制转换为 IEnumerable。 若要循环访问 ViewData.Model 的内容,这是必需的。 此处的另一个选项是创建强类型视图。 创建强类型视图时,将 ViewData.Model 属性强制转换为视图的代码隐藏类中的特定类型。

如果在修改 HomeController 类和索引视图后运行应用程序,则会出现空白页。 你将看到一个空白页,因为 tblMovies 数据库表中没有电影记录。

若要将记录添加到 tblMovies 数据库表,请右键单击“服务器资源管理器”窗口中的 tblMovies 数据库表 (Visual Web Developer) 中的“数据库资源管理器”窗口,然后选择菜单选项 “显示表数据”。 可以使用显示的网格插入电影记录, (见图 5) 。

插入影片

图 06:插入电影 (单击以查看全尺寸图像)

将一些数据库记录添加到 tblMovies 表并运行应用程序后,你将看到图 7 中的页面。 所有电影数据库记录都显示在项目符号列表中。

使用“索引”视图显示电影

图 07:使用“索引”视图显示电影 (单击以查看全尺寸图像)

使用存储库模式

在上一部分中,我们直接在控制器操作中使用 LINQ to SQL 类。 我们直接从 Index () 控制器操作使用了 MovieDataContext 类。 对于简单的应用程序,这样做没有问题。 但是,当你需要生成更复杂的应用程序时,在控制器类中直接使用 LINQ to SQL 会产生问题。

在控制器类中使用 LINQ to SQL 会使将来难以切换数据访问技术。 例如,你可能决定从使用 Microsoft LINQ to SQL 切换到使用 Microsoft 实体框架作为数据访问技术。 在这种情况下,需要重写访问应用程序中数据库的每个控制器。

在控制器类中使用 LINQ to SQL 还会使为应用程序生成单元测试变得困难。 通常,在执行单元测试时,不希望与数据库交互。 你想要使用单元测试来测试应用程序逻辑,而不是数据库服务器。

为了构建能够更适应未来更改且更易于测试的 MVC 应用程序,应考虑使用存储库模式。 使用存储库模式时,将创建一个单独的存储库类,其中包含所有数据库访问逻辑。

创建存储库类时,将创建一个接口,该接口表示存储库类使用的所有方法。 在控制器中,针对 接口而不是存储库编写代码。 这样,就可以在将来使用不同的数据访问技术实现存储库。

清单 3 中的接口名为 IMovieRepository,它表示名为 ListAll () 的单个方法。

清单 3 – Models\IMovieRepository.vb

Public Interface IMovieRepository
     Function ListAll() As IList(Of Movie)
End Interface

清单 4 中的存储库类实现 IMovieRepository 接口。 请注意,它包含一个名为 ListAll () 的方法,该方法对应于 IMovieRepository 接口所需的方法。

清单 4 - Models\MovieRepository.vb

Public Class MovieRepository Implements IMovieRepository
         Private _dataContext As MovieDataContext

         Public Sub New()
              _dataContext = New MovieDataContext()
         End Sub

         Public Function ListAll() As IList(Of Movie) Implements IMovieRepository.ListAll
              Dim movies = From m In _dataContext.Movies _
                   Select m
              Return movies.ToList()
         End Function
End Class

最后,清单 5 中的 MoviesController 类使用存储库模式。 它不再直接使用 LINQ to SQL 类。

清单 5 – Controllers\MoviesController.vb

using System.Web.Mvc;
using MvcApplication1.Models;

namespace MvcApplication1.Controllers
{
    Public Class MoviesController 
        Inherits System.Web.Mvc.Controller

             Private _repository As IMovieRepository

             Sub New()
                  Me.New(New MovieRepository())
             End Sub

             Sub New(ByVal repository As IMovieRepository)
                  _repository = repository
             End Sub

             Function Index()
                  Return View(_repository.ListAll())
             End Function
    End Class
}

请注意,清单 5 中的 MoviesController 类具有两个构造函数。 第一个构造函数(无参数构造函数)在应用程序运行时调用。 此构造函数创建 MovieRepository 类的实例,并将其传递给第二个构造函数。

第二个构造函数具有单个参数:IMovieRepository 参数。 此构造函数只是将 参数的值分配给名为 _repository 的类级字段。

MoviesController 类正在利用称为依赖关系注入模式的软件设计模式。 具体而言,它使用的是称为构造函数依赖关系注入的内容。 有关此模式的详细信息,请阅读 Martin Fowler 的以下文章:

http://martinfowler.com/articles/injection.html

请注意,除了第一个构造函数) 与 IMovieRepository 接口交互,而不是实际 MovieRepository 类之外,MoviesController 类中的所有代码都 (。 代码与抽象接口交互,而不是接口的具体实现。

如果要修改应用程序使用的数据访问技术,只需使用使用备用数据库访问技术的类实现 IMovieRepository 接口。 例如,可以创建 EntityFrameworkMovieRepository 类或 SubSonicMovieRepository 类。 由于控制器类是针对接口编程的,因此可以将 IMovieRepository 的新实现传递给控制器类,该类将继续工作。

此外,如果要测试 MoviesController 类,则可以将假电影存储库类传递给 MoviesController。 可以使用实际上不访问数据库的类实现 IMovieRepository 类,但该类包含 IMovieRepository 接口的所有必需方法。 这样,就可以对 MoviesController 类进行单元测试,而无需实际访问实际数据库。

总结

本教程的目的是演示如何利用 Microsoft LINQ to SQL 创建 MVC 模型类。 我们检查了在 ASP.NET MVC 应用程序中显示数据库数据的两种策略。 首先,我们创建了 LINQ to SQL 类,并直接在控制器操作中使用这些类。 通过在控制器中使用 LINQ to SQL 类,可以快速轻松地在 MVC 应用程序中显示数据库数据。

接下来,我们探索了一个稍微困难一些但肯定更良性的显示数据库数据的路径。 我们利用了存储库模式,将所有数据库访问逻辑放在单独的存储库类中。 在控制器中,我们针对接口而不是具体类编写了所有代码。 存储库模式的优点是,它使我们能够在将来轻松更改数据库访问技术,并使我们能够轻松测试控制器类。