zoukankan      html  css  js  c++  java
  • 使用VS2005 DataSet设计器实现数据访问层

    在早期的数据库应用程序中,大多都是客户端直接访问数据库。而随着程序越来越复杂,系统设计人员开始意识到需要在客户端和数据库之间架起一座桥梁,这就是所谓的数据访问层,这样一来,不但可以使数据库更安全,而且增加了客户端对数据库的透明性。这种结构也就是我们常说的三层结构。

        一个出色的数据访问层应该可以适用大多数商业应用程序,无论这个程序是基于C/S、Web还是直接在客户端使用。数据访问层的主要作用是在客户端获取或请求数据库服务之前进行一系列的处理,如对请求和获得的数据进行二次加工,或封装一些常用的代码。当然,我们也可以选择不使用数据访问层,通常最容易想的方法就是设计一些通用的类,并将常用的功能封装进去,或使用代码自动生成器来生成代码。这样做虽然可以在一定程序上缓解了程序的复杂度,但我们仍然要编写大量的代码,至少操作数据库的SQL语句需要手工编写。

    如果我们正在使用Visual Studio2005,那么实现所谓的数据访问层就容易的多了。在VS2005中DataSet设计器已经得到非常大的改进,通过DataSet设计器我们几乎可以不用写数据访问语句就可以完全很复杂的数据库操作。在本文中,将引领读者了解VS2005 Dataset的新特性,并使读者掌握如何使用这些新特性。同时还就使用Dataset设计器所带来的正面和负面效应进行了详细的阐述。

    一、DataSet简介
    在一般情况下,Dataset是一些通过Visual Studio设计器自动产生的类。这些类从ADO.NET DataSet、DataTable和DataRow继承,并提供一些用于访问数据的方法,并在DataSet中包含一个特殊的schema。我们可以在Visual Studio中通过拖放操作来生成Dataset类,并通过设计相应的属性来满足我们的需要。如果从底层来看,每生成一个Dataset,就相当于生成一个基于XML的XSD文件,在这个文件中包含了DataSet中的Schema。这个XSD文件还包含了一些和产生的数据源相关的一些注释。然后Visual Studio使用XSD文件自动产生的代码文件,这些代码文件同时包含了Dataset的定义。
     
    当我们在应用程序中使用数据库时,数据一般被表示成不同的商业实体,如Customers、Products、Employees等。为了和这些数据一起工作,需要将它们以商业实体的形式封装。如可以为每个实体写一个定制的类,同时这些类应该为需要处理的数据提供相应的接口。当然,为了方便处理多个实体对象,我们还需要为每一个实体建立一个集合类。
     
    Dataset将为我们描绘一个非常容易处理的数据世界。在这个世界中我们可以非常轻松地对数据进行增删改操作。从本质上讲,我们创建了一个Dataset,就相当于创建了一个自定义的类。这和我们手工写的类一样,所不同的是,这是使用可视化的设计器来完成的。同时这个Dataset会和数据库的schema保持同步。而Visual Studio的代码产生器将为我们完成所有的底层操作。另外,由于这些Dataset从ADO.NET的相应类型继承,因此,它们可以继承丰富的数据操作功能。这些功能还可以和Windows Forms或ASP.NET的数据绑定结合使用,如果使用了数据绑定功能,那么我们的工作量将会大幅度缩减。
     
    最后,也是最重要的,当我们在Visual Studio 2005中创建一个Dataset,同时也为每一个表创建一个适配器,并将这些适配器加到Dataset中。表适配器是真正访问数据库的组件,我们可以直接使用它对数据进行操作。它封装了数据库连接,数据适配器和Command对象集,我们可以用这些Command对象集来执行SQL语句。
       
    二、到底是使用DataSet还是使用商业实体对象

        长久以来在.NET领域一直存在着一个争论:是否需要使用DataSet?我们从第一部分的描述已经得知,Dataset在使用上是非常容易的,我们可以通过可视化的设计器来自动生成Dataset,同时将生成处理商业实体数据的API,并且Dataset已经支持很多高级特性了,如变化跟踪、排序、过滤和搜索。而一些反对使用Dataset的人则认为在.Net1.1中的Dataset的性能是非常差的。这些性能问题主要表现在如果数据量非常大时,由于Dataset实质上是已经序列化的XML,因此,如果将XML装载到Dataset中是速度是非常慢的。但这些问题已经在.NET2.0中得到了很大的提高。如果那么.NET1.1的使用者用过.NET2.0的话,也许会有一个全新的看法。
     
        DataSet的另一个用途是使用DataSet创建一个描述商业实体的对象类型,以及包含这些商业实体的集合类型。如果我们这样做,将结束编写大量代码的时代。如果我们在Visual Studio 2005和.NET 2.0中使用code snippets和泛型集合类的话,将会得到更佳的效果。但如果要想发挥DataSet所提供的全部功能,仍然得写很多代码。
     
        定制对象的一个好处是可以按着用户的意愿来控制数据,这主要是由内部暴露出来的API来完成的。对于那些喜欢纯面向对象设计方法的人来说,定制的商业实体将会使它们感到更舒适。在一般情况下,我们可以使用Dataset获得所有用定制商业实体获得的东西,但如果有些数据无法映射成自然的关系模型,那么DataSet就显得无能为力了。当然,如果你只想以获得显示的数据为目的,只允许用户对数据进行增、删、 改操作,那么使用DataSet设计器生成的Dataset还是非常好的。
     
        虽然在Visual Studio 2005中的Dataset支持商业实体的大多数功能。但我们还可以通过扩展类在商业实体中加入更复杂的验证和其他逻辑。每一个Dataset类型(Dataset, Datatable、Datarow和Table adapter)都在生成时都会产生另外一个类,我们可以在这个类中放入自己的代码。这是.Net2.0特有的性质,它允许使用自己的代码来弥补代码产生器的不足,并将自己的代码和自动产生的代码分开,这样做主要是为了防止在重新生成代码时将用户定制的代码覆盖。关于这方面更多的信息,可以参看.NET2.0的MSDN文档。

        关于DataSet的另一个争论是如果我们在编写表现层或业务逻辑层时是否应该使用Dataset,当然,有很多人反对这样做,因为这将使这两层和数据绑定得太紧。但事实上并不用这么做,首先,我们应该考虑使用存储过程来降低数据和应用程序之间的耦合度。我们可以很好的将存储过程和应用程序中要使用的商业实体数据很好的工作。另外,如果我们还想用其他方法降低耦合度的话,也可以将Dataset中的数据转换为其他类型的数据或是定制的商业实体数据或直接转换成数据访问层。
     
        最后一个值得争论的东西就是在使用Web Services是,是否通过Dataset来返回数据。大多数人都赞成不使用DataSet返回数据,这是因为,DataSet是.NET专有的,而Web Services是为所以客户端而准备的,也就是说,Java、C++等非.NET语言也可以使用Web Services。这样一来,如果使用Dataset,其他的语言就很难处理数据了。当然,如果客户端是.NET,那么这样做是非常好的。但在一般情况下,客户端可能是任何开发工具,所以笔者建议最好还是不返回DataSet为好。  

          如果我们想在开发.NET应用中大幅度地提高生产力,就应考虑适当地使用本文所讨论的Dataset。Dataset最大的优点是可以通过Visual Studio 2005产生一个table adapter类,这个类有点象data adapter。设计器允许我们地生成在table adapter中的查询方法,而我们并不用写那么多和ADO.NET相关的代码。为了更好地演示Dataset的功能,下面将给出一个实例来说明Dataset的强大。
    三、实例

        为了使问题更具体,在这一部分我们将使用table adapter创建一个简单的例子。在本例中我们将使用SQL Server2000中的Northwind做为数据源。要做的第一件事就是从Server Explorer中得到Northwind的数据库连接。为了达到这个目的,我们可以右击Server Explorer中的数据连接,选择加连接(Add Connection),然后按着提示一步步地进行下去。

        虽然Northwind是一个很好的实例数据库,但它并没有更好地支持存储过程进行CRUD操作(Create,Retrieve,Update和Delete)。而且在表中也没有一些用于帮助优化并发效率的列。为了使本文的例子可以更好的运行,需要运行一下本文提供了一个脚本文件(可以在查询分析器中执行这个脚本文件)。这个脚本在Employees表中加了一个datetime列,以及一些用于CRUD操作的存储过程。要想正确运行本文提供的例子,必须要依靠这些对数据库的修改。这些新加的存储过程包括SelectEmployees、UpdateEmployees、InsertEmployees和DeleteEmployees,这四个存储过程将处理CRUD操作。

        在使用SQL脚本修改Northwind数据库之后,启动Visual Studio 2005并创建一个新的叫NorthwindDataAccess的类库工程,如图1所示。在这个工程中默认生成了一个Class1.cs文件,其实这个文件对本文的例子没什么用,读者可以将它删除。然后右NorthwindDataAccess工程,选择添加 > 新建项 ...,从弹出对话框中选择“数据集”,如图2所示。这样就将一个数据集定义加到工程中了。



    1:创建一个数据访问类库工程



     图2 在工程中加入一个Dataset定义文件
     
        接下来我们将从右边的服务器资源管理器中选择一些表加入到Dataset中。首先应建立Northwind数据连接,并打开“存储过程”结点,选择SelectEmployees存储过程。并将这个存储过程拖到Dataset设计器。
        当你做完后,就会看到一个加入Employees表中字段的表定义。这些定义是基于存储过程返回的Select表达式的。我们可以将SelectEmployees重新命名为Employees。如图3所示。在图3中我们还会看到Employees表的底端已经将EmployeesTableAdapter加入进来。这个适配器是我们最先介绍的适配器。当我们保存这个工程时,Visual Studio将在后台自动产生一些代码。

    图3 Employees表定义和表适配器


        在上面介绍的简单拖动后,Visual Studio会创建很多新的类型定义。EmployeesDataSet是最顶层的容器类。而EmployeesDataTable将提供一个实体类。最后,EmployeesTableAdapter将会使用SelectEmployees存储过程获得数据。当我们切换到代码区后,就会发现,Visual Studio至少为我们产生了1000多行代码。这些代码在EmployeesDataSet.Designer.cs文件中可以找到。

        为了使问题更具体,在这一部分我们将使用table adapter创建一个简单的例子。在本例中我们将使用SQL Server2000中的Northwind做为数据源。要做的第一件事就是从Server Explorer中得到Northwind的数据库连接。为了达到这个目的,我们可以右击Server Explorer中的数据连接,选择加连接(Add Connection),然后按着提示一步步地进行下去。

        虽然Northwind是一个很好的实例数据库,但它并没有更好地支持存储过程进行CRUD操作(Create,Retrieve,Update和Delete)。而且在表中也没有一些用于帮助优化并发效率的列。为了使本文的例子可以更好的运行,需要运行一下本文提供了一个脚本文件(可以在查询分析器中执行这个脚本文件)。这个脚本在Employees表中加了一个datetime列,以及一些用于CRUD操作的存储过程。要想正确运行本文提供的例子,必须要依靠这些对数据库的修改。这些新加的存储过程包括SelectEmployees、UpdateEmployees、InsertEmployees和DeleteEmployees,这四个存储过程将处理CRUD操作。

        在使用SQL脚本修改Northwind数据库之后,启动Visual Studio 2005并创建一个新的叫NorthwindDataAccess的类库工程,如图1所示。在这个工程中默认生成了一个Class1.cs文件,其实这个文件对本文的例子没什么用,读者可以将它删除。然后右NorthwindDataAccess工程,选择添加 > 新建项 ...,从弹出对话框中选择“数据集”,如图2所示。这样就将一个数据集定义加到工程中了。



    1:创建一个数据访问类库工程



     图2 在工程中加入一个Dataset定义文件
     
        接下来我们将从右边的服务器资源管理器中选择一些表加入到Dataset中。首先应建立Northwind数据连接,并打开“存储过程”结点,选择SelectEmployees存储过程。并将这个存储过程拖到Dataset设计器。
        当你做完后,就会看到一个加入Employees表中字段的表定义。这些定义是基于存储过程返回的Select表达式的。我们可以将SelectEmployees重新命名为Employees。如图3所示。在图3中我们还会看到Employees表的底端已经将EmployeesTableAdapter加入进来。这个适配器是我们最先介绍的适配器。当我们保存这个工程时,Visual Studio将在后台自动产生一些代码。

    图3 Employees表定义和表适配器


        在上面介绍的简单拖动后,Visual Studio会创建很多新的类型定义。EmployeesDataSet是最顶层的容器类。而EmployeesDataTable将提供一个实体类。最后,EmployeesTableAdapter将会使用SelectEmployees存储过程获得数据。当我们切换到代码区后,就会发现,Visual Studio至少为我们产生了1000多行代码。这些代码在EmployeesDataSet.Designer.cs文件中可以找到。
    四、加入其他的存储过程
     
        当我们拖一个SELECT存储过程到设计器上时,适配器仅仅实现了填充所产生表的代码。设计器在EmployeesDataSet.Designer.cs中生成了一个Fill方法,这个方法的第一个参数是EmployeesDataTable类型,而Fill就是用来向EmployeesDataTable中添入数据的。除了Fill方法,设计器还产生了一个GetData方法,这个方法将根据EmployID创建一个EmployeesDataTable实例。这个实例将通过GetData的返回值返回。这样用户将不用手工创建它了。
       
        下一步就是曾加适当的UPDATE、INSERT和DELETE存储过程。为了达到这个目的,我们可以利用另外一个简单的模板来完成。为了启动模板,单击Employees并选中它,然后单击鼠标右键,选择配置菜单项。这时将启动TableAdapter配置向导。在这个配置向导中将允许修改已经产生的存储过程。由于adapter的第一个存储过程已经产生,因此,SelectEmployees将作为默认的存储过程显示在SELECT标签上,如图4所示:


    图4 TableAdapter配置向导
     
        使用这个向导,我们可以很容易地从下拉列表框中选择响应的InsertEmployees,UpdateEmployees和DeleteEmployees存储过程。在右侧的表格中将显示所选的存储过程的参数。如果某个参数名匹配列名,这个向导将为我们自动匹配,这将省去了我们很多的麻烦。
        当我们做完以上操作后,就可以点击完成按钮来结束这一步了。至于这个向导的其他步骤,是用来进行更高级的配置,由于这些在本文中并不涉及,因此,本文对此并不探讨,感兴起的读者可以查阅其他的资料。
  • 相关阅读:
    彼之蜜糖,吾之砒霜——聊聊软件开发中的最佳实践
    WebAPI框架里设置异常返回格式统一
    Entity Framework Plus
    实体框架自定义代码优先约定(EF6以后)
    npm 切换淘宝镜像几种方式
    EntityFramework中Json序列化的循环引用问题解决--Newtonsoft.Json
    Json序列化循环引用的问题
    Windows Service 之 安装失败后的删除
    Windows Service 之 详解(二)
    Windows Service 之 详解(一)
  • 原文地址:https://www.cnblogs.com/longyi/p/1459497.html
Copyright © 2011-2022 走看看