Linq to SQL与.net MVC

什么是 Model 类?

MVC 模型包含未包含在 MVC 视图或 MVC 控制器中的所有应用程序逻辑。其特别之处在于,MVC 模型包含所有应用程序业务和数据访问逻辑。

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

在本教程中,作者将使用 LINQ to SQL 查询并更新数据库。LINQ to SQL 提供了一种非常简单的方法来与 Microsoft SQL Server 数据库交互。但是,我们并未将 ASP.NET MVC Framework 以任何方式附加到 LINQ to SQL,了解这一点非常重要。ASP.NET MVC 可以与任何数据访问技术兼容。

创建 Movie 数据库

在本教程中,为了说明如何构建 Model 类,我们将构建一个简单的 Movie 数据库应用程序。第一步是创建新的数据库。右键单击 Solution Explorer 窗口中的 App_Data 文件夹,然后选择菜单选项 Add,New Item。选择 SQL Server Database模板,将其命名为 MoviesDB.mdf,然后单击Add 按钮(如图 1 所示)。

图 1:添加新的 SQL Server 数据库(单击查看大图

创建新的数据库后,可以双击 App_Data 文件夹中的 MoviesDB.mdf 文件打开数据库。双击 MoviesDB.mdf 文件打开 Server Explorer 窗口(如图 2 所示)。

在使用 Visual Web Developer 时,Server Explorer 窗口称为 Database Explorer 窗口。

图 2:使用 Server Explorer 窗口(单击查看大图

需要向数据库添加表示电影的表。右键单击 Tables 文件夹并选择菜单选项 Add New Table。选择此菜单选项将打开 Table Designer(如图 3 所示)。

图 3:Table Designer(单击查看大图

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

列名称

数据类型

允许空值

Id

Int

False

Title

Nvarchar(200)

False

Director

Nvarchar(50)

False

需要对 Id 列进行两项特殊的处理。首先,需要将 Id 列标记为主键列,方法是在 Table Designer 中选择列,然后单击钥匙图标。LINQ to SQL 要求在执行插入或更新数据库时指定主键列。

接下来,需要将 Id 列标记为 Identity 列,方法是将 Is Identity 属性赋值为 Yes(如图 3 所示)。每当将新数据行添加到表时,都会自动给 Identity 列分配一个新序号。

创建 LINQ to SQL 类

我们的 MVC 模型将包含表示 tblMovie 数据库表的 LINQ to SQL 类。要创建这些 LINQ to SQL 类,最简单的方法是右键单击 Models 文件夹,选择Add,New Item,选择 LINQ to SQL Classes 模板,将类命名为 Movie.dbml,然后单击Add 按钮(如图 4 所示)。

图 4:创建 LINQ to SQL 类(单击查看大图

创建 Movie LINQ to SQL 类之后,Object Relational Designer 将立即出现。可以将数据库表从 Server Explorer 窗口拖到 Object Relational Designer 上,以创建代表特殊数据库表的 LINQ to SQL 类。我们需要将 tblMovie 数据库表添加到 Object Relational Designer 上(如图 5 所示)。

图 5:使用 Object Relational Designer(单击查看大图

默认情况下,Object Relational Designer 创建一个与拖放到 Designer 上的数据库表名称相同的类。但是,我们不希望类的名称为tblMovie。因此,单击 Designer 中的类名称并将其更改为 Movie。

最后,要记住单击 Save按钮(软盘图标)保存 LINQ to SQL 类。否则,Object Relational Designer 将不会生成 LINQ to SQL 类。

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

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

首先,我们需要修改 HomeController 类。该类位于应用程序的 Controllers 文件夹中。将该类修改为如程序清单 1 所示。

程序清单 1Controllers\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);
          }
     }
}

程序清单 1 中的 Index() 操作使用 LINQ to SQL DataContext 类 (MovieDataContext) 表示 MoviesDB 数据库。MoveDataContext 类由 Visual Studio Object Relational Designer 生成。

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

为了显示电影,需要修改 Index 视图。Index 视图位于 Views\Home\ 文件夹中。将 Index 视图更新为如程序清单 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>

请注意,修改后的 Index 视图在开头包含<%@ import namespace %>指令。此指令导入MvcApplication1.Models命名空间。必须具备此命名空间,才能使用视图中的model类(即 Movie类)。

程序清单 2 中的视图包含foreach循环,该循环遍历所有由ViewData.Model属性表示的项,显示了每个movieTitle 属性值。

请注意,ViewData.Model属性的值被分配为IEnumerable。为了遍历ViewData.Model的内容,这是必须的。此处的另一个选项是创建强类型的view。创建强类型的view时,会将ViewData.Model属性分配为某个视图的代码隐藏类中的特定类型。

如果在修改 HomeController 类和 Index 视图后运行应用程序,则将得到空白页面。得到空白页面的原因是tblMovies 数据库表中没有电影记录。

为了在tblMovies数据库表中添加一些记录,请右键单击 Server Explorer 窗口(Visual Web Developer 中的 Database Explorer 窗口)中的tblMovies数据库表,然后选择菜单选项 Show Table Data。使用出现的网格可以插入movie记录(如图 6 所示)。

图 6:插入电影(单击查看大图

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

图 7:使用 Index 视图显示电影(单击查看大图

使用 Repository 模式

在前一部分中,我们直接在控制器操作中使用了 LINQ to SQL 类。我们直接从 Index()控制器操作使用了 MovieDataContext类。对于简单的应用程序来说,这样做没有任何不妥之处。然而,如果需要构建更加复杂的应用程序,那么直接在控制器类中使用 LINQ to SQL 就会出现问题。

在控制器类中使用 LINQ to SQL 使得将来切换数据访问技术变得非常困难。例如,您可能决定不使用 Microsoft LINQ to SQL,而改为使用 Microsoft Entity Framework 作为数据访问技术。在这种情况下,需要重新编写应用程序中每个访问数据库的控制器。

在控制器类中使用 LINQ to SQL 还使得难以构建应用程序的单元测试。通常,在执行单元测试时不希望与数据库交互。您希望使用单元测试来测试应用程序逻辑,而不是数据库服务器。

为了构建在将来更适合更改和易于测试的 MVC 应用程序,应该考虑使用 Repository 模式。在使用 Repository 模式时,会创建单独的包含所有数据库访问逻辑的储存库类。

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

程序清单 3 中的接口名称为IMovieRepository,它代表一个名称为ListAll()的方法。

程序清单 3 Models\IMovieRepository.cs

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

程序清单 4 中的 Repository 类实现 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
         }
}

最后,程序清单 5 中的 MoviesController 类使用 Repository 模式。它不再直接使用 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());
              }
         }
}

请注意,程序清单 5 中的MoviesController类有两个构造方法。在应用程序运行时调用第一个构造方法(parameterless 构造方法)。此构造方法创建MovieRepository类的一个实例,然后将其传递给第二个构造方法。

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

MoviesController 类利用称为 Dependency Injection 的软件设计模式。在此处,它使用的技术称为 Constructor Dependency Injection。请阅读以下由 Martin Fowler 撰写的文章,了解更多有关此模式的信息:

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

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

如果想修改应用程序使用的数据访问技术,则可以简单地通过使用替代数据访问技术的类实现IMovieRepository接口。例如,可以创建一个EntityFrameworkMovieRepository类或SubSonicMovieRepository类。由于控制器类是针对接口编写的,因此可以将IMovieRepository的新实现传递给控制器类,而该类将继续工作。

更进一步,如果想测试 MoviesController类,则可以将仿造的电影储存库类传递给MoviesController。可以使用实际上不访问数据库,但包含所有IMovieRepository接口要求的方法的类来实现IMovieRepository类。通过这种方式,可以在不访问实际数据库的情况下对MoviesController类进行单元测试。

总结

本教程的目的是向读者介绍如何利用 Microsoft LINQ to SQL 创建 MVC 模型类。我们研究了两种在 ASP.NET MVC 应用程序中显示数据库数据的策略。首先,我们创建了 LINQ to SQL 类并直接在控制器操作中使用该类。在控制器中使用 LINQ to SQL 类可以轻而易举地在 MVC 应用程序中显示数据库数据。

接下来,我们研究了一种稍微困难,但更加优越的显示数据库数据的方法。我们利用了 Repository 模式并将所有数据库访问逻辑放到单独的储存库类中。在控制器中,我们针对接口而不是具体的类编写所有代码。Repository 模式的优势在于可以在将来轻松地更改数据库访问技术和测试控制器类。


转载msdn http://msdn.microsoft.com/zh-cn/dd408820.aspx 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
API:应用编程接口,是一个新的(API)应用编程接口 本质上它是命名空间和类的一个集合,他的目标是:查询任意来源的数据。 数据库、业务对象、XML文件、一个数据集 1、所需要数据均出自相同的数据源,可能性很小。数据库、业务对象、XML文件、一个数据集,Web服务端 2、访问数据的难易程度完全取决于数据的存储位置。访问一个内存中的对象会比访问XML文件数据库容易。 3、原数据自身一般不是最主要显示的结果。一旦要进行整理,它就须要排序、修改、分组、调序。循环遍历,合并入一个数据池,等等。 List<Book> book=GetBooks(); //排序 Books.SortByPrice(delegate(Book first,Book second)) { Return((double)(second.Price-first.Prince)); } //遍历运算求总计 Double totallncome=0; Books.Foreach(delegate(Book book)) { Totallcome+=(book.Price*book.TotalSales); } 以上六行包含了排序,循环,合并运算,价格数据不是通过不同的类别的电子表格,Web服务或XML输入的 让数据源更易于访问,可以连接不同的数据源的数据,并且对他们执行标准化的数据处理操作,全部只需要一行代码完成。 例如:提供可以确保所有数据字段是通用类的操作,这样就必担心从数据库获取数据时类型正确转换问题。 一些数据源本没有DataProvider的支持,可以提供一种措施易于开发人员做功能扩展,创建一个支持这些数据源的Provider。 Var Query=from book in Books Where book.QuarterlySales>0 Select book=>{Name,(Price*QuarterlySales)} 四个属性和一个静态方法,该方法把五本书列表返回给任何需要该数据的页面,这里有一个C#3.0语言中的一个特性一一对象新转化器(object)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值