数据库连接

本文转自: http://www.anqn.com/c/2008-07-10/a0998632.shtml
使用数据库连接

    为了访问数据库,需要提供某种类型的连接参数,例如运行数据库的机器,和登录凭证。使用ADO的用户会很快熟悉.NET连接类OleDbConnection和SqlConnection,图21-1显示了连接类及它们支持的接口。

    在本章的示例中,使用Northwind数据库,它是和.NET Framework SDK示例一起安装的。下面的代码段说明了如何创建、打开和关闭Northwind数据库的连接。
    using System.Data.SqlClient;
    string source = "server=(local)\\NetSDK;" +"integrated security=SSPI;" +"database=Northwind";
    SqlConnection conn = new SqlConnection(source);
    conn.Open();
    // Do something useful
    conn.Close();


图  21-1

    如果以前使用过ADO或OLE DB,就会很熟悉连接字符串。如果使用的是OleDb提供程序,就应能剪切和粘贴旧代码。在该示例的连接字符串中,使用的参数如下所示。连接字符串中的参数用分号分隔开。
    ●  server=(local)\\NetSDK:表示要连接的数据库服务器。SQL Server允许在同一台机器上运行多个不同的数据库服务器进程,所以这里在本地机器上连接NetSDK进程。
    ●  integrated security=SSPI:这个参数使用Windows Authentication连接数据库,最好在源代码中使用这个参数,而不是用户名和密码。
    ●  database=Northwind:这描述了要连接的数据库实例。每个SQL Server进程都可以有几个数据库实例。

    这个示例使用定义的连接字符串打开数据库连接,再关闭该连接。连接打开后,就可以对数据源执行命令,完成后,就可以关闭连接。

    SQL Server有另一个模式的身份验证。它可以使用Windows集成的安全性,这样在登录时提供的证书就会传送给SQL Server。这适合于删除连接字符串的uid 和 pwd部分,并添加Integrated Security=SSPI。

    在本章的下载代码中,有一个文件Login.cs简化了本章的示例。它链接了所有的示例代码,包括用于这些示例的数据库连接信息;可以修改该文件,使用自己的服务器名称、用户和密码。在默认情况下,该文件使用Windows集成的安全性,但是可以根据需要修改用户名和密码。

    高效地使用连接

    一般情况下,当在.NET中使用“稀缺”的资源 时,例如数据库连接、窗口或图形对象, 最好确保每个资源在使用后立即关闭。尽管.NET的设计人员实现了自动的垃圾收集,垃圾最终都会被回收,但仍需要尽可能早地释放资源,以避免出现资源匮乏的情况。

    当编写访问数据库的代码时,这是非常明显的,因为使连接打开的时间略长于需要的时间,就可能影响其他会话。在极端的情况下,不关闭连接会使其他用户无法进入一整组数据表,极大地降低了应用程序的性能。关闭数据库连接应是强制的,所以本节讨论如何构建代码,把一直打开资源的风险降到最低。

    主要有两种方式可以确保数据库连接等类似的“稀缺”资源在使用后立即释放。
    1. 第一种方式—— 利用try…catch…finally语句块
    确保释放资源的第一种方式是利用try…catch…finally块,确保在finally块中关闭任何已打开的连接。下面是一个小示例:
    try
    {
       // Open the connection
       conn.Open();
       // Do something useful
    }

catch ( Exception ex )
    {
       // Do something about the exception
    }
    finally
    {
       // Ensure that the connection is freed
       conn.Close ( ) ;
    }

    在finally块中,可以释放已经使用的任何资源。这种方式的惟一麻烦是必须确保关闭连接。很容易忘记在finally块中添加关闭连接的命令,所以应在编码风格上添加一些不容易出现反常情况的内容。

    另外,在给定的方法中可能会打开许多资源(例如两个数据库连接和一个文件),这样try…catch…finally块的层次有时可能不容易看懂。但还有另一个方式可以确保资源的关闭—— 使用using语句。

    第二种方式—— 使用using语句块
    在开发C#的过程中,.NET在对象不再引用之后清理它们的方法是使用非决定性的析构方式,这已经引起了一个非常热烈的讨论。

    在C++中,对象只要使用完毕,就会自动调用其析构函数。这对于设计基于资源的类的人员来说,是一个非常好的消息,因为如果用户忘记关闭资源,使用析构函数是非常理想的。只要对象使用完毕,就会调用C++析构函数。所以,如果出现了异常,但没有捕获,有析构函数的所有对象就会调用它们的析构函数。

    在C#和其他托管语言中,没有自动、决定性的析构方式,而是有一个垃圾收集器,它会在未来的某个时刻释放资源。它是非决定性的,因为我们不能确定这个过程在什么时候发生。忘记关闭数据库连接可能会导致.NET可执行程序的各种问题。幸运的是,我们还有解决的方法。下面的代码说明了如何使用using子句确保实现IDisposable接口(详见第4章)的对象在退出块时立即被释放。
    string source = "server=(local)\\NetSDK;" +" integrated security=SSPI;" +"database=Northwind";
    using ( SqlConnection conn = new SqlConnection ( source ) )
    {
       // Open the connection
       conn.Open ( ) ;
       // Do something useful
    }

    在这个示例中,无论块是如何退出的,using子句都会确保关闭数据库连接。

    查看一下连接类的Dispose()方法的IL代码,它们都检查连接对象的当前状态,如果其状态为打开,就调用Close()方法。浏览.NET程序集的一个强大工具是Reflector(可以从/www.aisto.com/roeder/dotnet/上获得)。这个工具允许查看任何.NET方法的IL代码,还可以把IL代码反编译为源代码,让我们轻松地确定给定的方法的作用。

    在编程时,应至少使用这两个方法中的一个,或者两个方法都使用。无论在哪里获得资源,最好都使用using ()语句,因为尽管我们都会编写Close()语句,但有时会忘记,此时using子句就会发挥作用。这两种方式都没有好的异常处理方式来替代,所以在大多数情况下,最好组合使用这两种方法,如下面的示例所示。
    try
    {
       using (SqlConnection conn = new SqlConnection ( source ))
       {
          // Open the connection
          conn.Open ( ) ;
          // Do something useful
          // Close it myself
          conn.Close ( ) ;
       }
    }
    catch (Exception e)
    {
       // Do something with the exception here...
    }

    这里显式调用了Close(),但这是不必要的,因为using子句将确保在任何情况下都执行关闭操作。但是,应确保像这样的资源尽可能早地释放。因为在块的其余部分可能有更多的代码,而在这些地方没有必要锁定资源。

    另外,如果在using块中出现了异常,using子句就会确保在资源上调用IDisposable.Dispose方法,在本例中将确保总是关闭数据库连接。这样,与必须确保在异常子句中关闭连接相比,代码的可读性更高。

    最后,如果编写一个封装资源的类,无论该资源是什么,都应实现IDisposable接口,关闭资源。这样,任何使用该类的代码都可以利用using()语句,以确保资源被释放。

你可能感兴趣的:(数据库连接)