在新的.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上的箭头符号说明了不同层之间的交互。说明如下:
(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代码。
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自动生成。
在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 类自动负责打开数据库连接,执行数据操作和关闭连接。
|