在.NET 3.5 平台上使用LINQ to SQL创建三层/多层Web应用系统(一)
 
2008-12-10 来源:EntLib.com
 

在新的.Net Framework 3.5平台上,Microsoft发布了LINQ(C# 3.0, VB.Net 9.0)-集成语言查询(Language-Integrated Query),也就是通过编程语言来查询数据:

  • 数据库 (LINQ to SQL)
  • DataSet 数据集(LINQ to Dataset)
  • XML文档 (LINQ to XML) 
  • 实体对象 (LINK to Entities)

本文将演示如何在ASP.NET 3.0平台上,使用LINQ to SQL构建多层的Web应用程序。在当前的编程领域中,创建N-Tier应用程序成为一般的要求,且.NET Framework 提供了灵活的支持。一般而言,N-Tier应用程序有如下几个层:1. 表示层;2. 业务逻辑层;3. 数据访问层;4. 数据库层。每一层均完成特定的任务。本篇文章中介绍的架构和经典的N-Tier相似,不过数据库层替换新的DataLinq 层,使用LINQ to SQL 完成数据操作。

图1.1:基于LINQ to SQL的N-Tier架构

架构思考

如果你有大型ASP.NET项目的经历,你可能会注意到更多的时间花在写组件代码,而不是Web页面代码。有时,组件的设计和管理成为一个费时的过程,你可能正遇到架构方面的问题-寻找最好的方式来设计Web应用程序。

我写这篇文章的想法是介绍一个好的设计模式,并不是得到一个结论或者声明这是一个最好的N-Tier应用程序的设计模式。因为对于架构设计,每一个开发人员总是有自己的观点,所以任何合适的架构阐述都是有争议的。然而,如图1.1所示,分离不同的代码到不同的层总是一个好的实践。按这样组织代码,可以更方便地维护和扩展应用程序。

在图1.1中,你可以看到业务组件分割到不同的层。组织代码最好的方法是为每一个业务组件创建不同的类库(Class Library)。Visual Studio允许在同一个Solution中创建多个项目。因此,我们可以在同一个Solution中加入ASP.NET 应用程序和类库Class Library项目。当你在编译Solution时,每一个项目都会生成在bin目录下生成一个assembly程序集文件。方法1:我们可以手动复制.DLL文件到应用程序的bin目录。方法2:增加项目引用。当你编译Solution时,第二种方法可以自动更新应用程序bin目录的程序集文件。通过这种方式组织代码,可以更容易修改/更新项目的特定代码,也容易从不同的Server上迁移代码。我不想深入探讨架构,这里我通过截屏来解释如何实现。

假定你已经具备经典3层架构应用程序的设计经验,我告诉你如何建立层与层之间的引用关系,接着你可以自己建立项目引用。图1.1上的箭头符号说明了不同层之间的交互。说明如下:

(1) 数据访问层引用Data Linq 层(EntLib.com 开源小组注: 原文说还需要引用业务外观(Business Facade)层,原文有误)。

(2) 业务外观(Business Facade)层引用Data Linq 层和数据访问层,因为业务外观层使用Data Linq层的业务实体来创建表实体(后面进行详细讨论),同时调用数据访问层的方法。

(3) 表现层引用Data Linq层和业务外观层。

LINQ to SQL

LINQ to SQL 提供了访问数据库的方法,且允许我们做所有数据库相关的操作,如查询、插入、更新和删除。LINQ to SQL消除了写存储过程和从数据访问层调用的过程,它可以在运行的时候自动生成合适的SQL脚本来进行数据库操作。在Visual studio中,你可以通过使用Add New Item 增加LINQ to SQL文件到项目中。下图1.4是Northwind数据库在Object Relational Designer 中的显示(EntLib.com 开源小组注:原文采用SampleDB数据库,这里我们采用Northwind 范例数据库)。当保存该文件时,LINQ to SQL自动创建一个CS文件或VB文件 – 用来访问数据库的DataContext类,还为设计器中的表创建一些必要的实体类。在设计器中的每一个表均有一个对应的实体类。

设计器中的表包含所有的数据库属性,包括表关系。设计器中的箭头标识表示数据库表的主键/外键关系。

EntLib.com 开源小组注:这里我们创建C# 项目,而不是原文采用的VB项目,因此后续的示例代码全部为C#,原文为VB代码。

DataContext 类

Solution 中的每一个LINQ to SQL设计器将自动创建一个DataContext类,用来查询数据库、检索数据记录和更新数据库操作的主要类,它包含了每一个表的属性。

实体类

LINQ to SQL为添加到设计器(.dbml文件)中的每一个表创建对应的实体类,这些实体类包含了强类型属性集合,映射到数据库中对应表的字段。LINQ to SQL使用这些实体类来生成数据操作的SQL脚本,同时,我们也可以创建实体类的实例,给实例赋值,然后在不同的层之间作为数据传输对象进行传递。(EntLib.com 开源小组注:这些实体类并不适合在WCF Service与Client 作为DTO传递,因为WCF对传输的实体类有特殊的attribute要求。对WCF Data Contract的要求,请您参加相关的文档。)

映射Mapping

DataContext类中的实体类和属性直接映射到对应数据表和字段。缺省情况下,在DataContext类中,LINQ使用继承抽象类MappingSource的AttributedMappingSource类来存放表和字段的映射信息,从数据库中检索记录和提交数据更新到数据库时需要这些映射信息。

重新生成DataContext类

当数据库表设计发生变化时,必须更新DataContext类。我们建议在任何修改/更新数据表时,重新生成整个DataContext类。首先,删除DataContext 类文件(C# / VB文件);然后保存该文件,并自动DataContext类。或者你右键点击.dbml文件,找到Run Custom Tool 选项,然后点击重新生成DataContext类文件。

创建Data Linq 层

下图1.2显示Data Linq层,包含了DataContext类和实体类。这些类对应的代码文件由Visual studio自动生成。

图1.2:Data Linq 层 – 详细视图

在solution中增加一个类库Class Library项目,然后增加LINQ to SQL到项目中。下图是Visual Studio 2008 增加一个新的LINQ to SQL的截屏,并在窗口中选择LINQ to SQL选项。

图1.3: 增加LINQ to SQL类

增加LINQ to SQL到项目中,将自动创建一个空白的设计器(.dbml文件),并附有server explorer的链接,同时也创建相关的dbml.layout文件(XML文件)和designer.cs文件(DataContext类文件 – http://www.EntLib.com 开源小组注:原文为VB文件)。打开server explorer,并建立到数据库的链接,然后导航到合适的数据库和表,接着拖放相关的表到设计器表面。最后,保存文件。现在,已经自动生成了包含相关的属性、方法的DataContext类和实体类。

为了演示的需要,我将使用Northwind 范例数据库(http://www.EntLib.com 开源小组注:原文采用自定义的sample数据库)。根据如下表结构,我们可以了解如何创建CURD操作层。如下图1.4显示含有这些表的dbml文件:

图1.4:LINQ to SQL设计器 - .dbml文件

下图1.5 是DataContext类和实体类的Class Diagram:


 图1.5:Data LINQ – Class Diagram

注:DataContext 类自动负责打开数据库连接,执行数据操作和关闭连接。


火龙果软件/UML软件工程组织致力于提高您的软件工程实践能力,我们不断地吸取业界的宝贵经验,向您提供经过数百家企业验证的有效的工程技术实践经验,同时关注最新的理论进展,帮助您“领跑您所在行业的软件世界”。
资源网站: UML软件工程组织