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

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) 。 “标识”列是一个列,每当向表添加新的数据行时,都会自动为其分配一个新编号。

创建 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 (请参阅图 5) 。

使用对象关系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.cs

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

namespace MvcApplication1.Controllers
{
     [HandleError]
     public class HomeController : Controller
     {
          public ActionResult Index()
          {
               var dataContext = new MovieDataContext();
               var movies = from m in dataContext.Movies
                    select m;
               return View(movies);
          }
     }
}

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

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

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

清单 2 - Views\Home\Index.aspx

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Index.aspx.cs" Inherits="MvcApplication1.Views.Home.Index" %>
<%@ Import Namespace="MvcApplication1.Models" %>
<asp:Content ID="indexContent" ContentPlaceHolderID="MainContent" runat="server">

     <ul>
          <% foreach (Movie m in (IEnumerable)ViewData.Model)

          { %>
               <li> <%= m.Title %> </li>
          <% } %>
     </ul>
</asp:Content>

请注意,修改后的索引视图在视图顶部包含 指令 <%@ import namespace %> 。 此指令导入 MvcApplication1.Models namespace。 我们需要此命名空间,以便处理视图中的 model 类(尤其是 Movie 类)。

清单 2 中的视图包含循环 foreach 访问 属性表示 ViewData.Model 的所有项的循环。 为每个 显示 movie属性的值Title

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

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

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

插入影片

图 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.cs

using System.Collections.Generic;
namespace MvcApplication1.Models
{
     public interface IMovieRepository
     {
          IList<Movie> ListAll();
     }
}

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

清单 4 - Models\MovieRepository.cs

using System.Collections.Generic;
using System.Linq;

namespace MvcApplication1.Models
{
     public class MovieRepository : IMovieRepository
     {
          private MovieDataContext _dataContext;

          public MovieRepository()
          {
                _dataContext = new MovieDataContext();
          }

          #region IMovieRepository Members

          public IList<Movie> ListAll()
          {
               var movies = from m in _dataContext.Movies
                    select m;
               return movies.ToList();
          }

          #endregion
     }
}

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

清单 5 – Controllers\MoviesController.cs

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

namespace MvcApplication1.Controllers
{
     public class MoviesController : Controller
     {
          private IMovieRepository _repository;

          public MoviesController() : this(new MovieRepository())
          {
          }

          public MoviesController(IMovieRepository repository)
          {
               _repository = repository;
          }

          public ActionResult Index()
          {
               return View(_repository.ListAll());
          }
     }
}

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

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

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

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

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

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

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

总结

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

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