连接数据库

使用连接字符串 

连接字符串包含作为参数传递给数据源的初始化信息。在设置后会立即分析连接字符串。语法错误将生成运行时异常,但是只有在数据源验证了连接字符串中的信息后,才可以发现其他错误。验证后,数据源设置启用该连接的各种选项。

连接字符串关键字

连接字符串的格式是使用分号分隔的键/值参数对列表:

keyword1=value; keyword2=value

忽略空格,关键字不区分大小写,尽管值可能会区分大小写,这取决于数据源的大小写。要加入包含分号、单引号或双引号的值,值必须加双引号。

有效的连接字符串语法依提供程序而异,从早期的 API(例如 ODBC)开始,经历了多年的发展。SQL Server .NET Framework 数据提供程序结合了早期语法中的许多元素,通常对常见的连接字符串语法更加宽容。有关 .NET 数据提供程序的连接字符串关键字的更多信息,请参见 ConnectionStringConnectionStringConnectionStringConnectionString

持续安全信息

连接字符串中 Persist Security Info 关键字的默认设置为 false。

Persist Security Info=false;

如果将该关键字设置为 true 或 yes,将允许在打开连接后,从连接中获得涉及安全性的信息(包括用户标识和密码)。如果在建立连接时必须提供用户标识和密码,最安全的方法是在使用信息打开连接后丢弃这些信息,在 Persist Security Info 设置为 false 或 no 时会发生这种情况。当您向不可信的源提供打开的连接,或将连接信息永久保存到磁盘时,这点尤其重要。如果将 Persist Security Info 保持为 false,可帮助确保不可信的源无法访问连接中涉及安全性的信息,并帮助确保任何涉及安全性的信息都不会随连接字符串信息在磁盘上持久化。

使用 Windows 身份验证

我们建议您使用 Windows 身份验证(通常称为集成安全性)连接到服务器数据库上。要指定 Windows 身份验证,可以对 SQL Server .NET Framework 数据提供程序使用下列两个键/值对中的任意一个:

Integrated Security=true;
Integrated Security=SSPI;

但是,只有第二个将适用于 OleDb .NET Framework 数据提供程序。为 ConnectionString 设置 Integrated Security=true 将引发异常。

对于 ODBC .NET Framework 数据提供程序,必须使用以下键/值对指定 Windows 身份验证。

Trusted_Connection=yes;

创建连接字符串

每个 .NET Framework 数据提供程序提供一个从 DbConnectionStringBuilder 继承的强类型连接字符串生成器类。连接字符串生成器使开发人员可以通过编程,基于用户输入创建语法正确的连接字符串,以及分析并重新生成现有的连接字符串。有关更多信息,请参见 SqlConnectionStringBuilderOleDbConnectionStringBuilderOdbcConnectionStringBuilderOracleConnectionStringBuilder

存储和检索连接字符串

我们建议您不要在代码中嵌入连接字符串。如果服务器的位置会更改,您的应用程序将需要重新编译。此外,编译成应用程序源代码的未加密连接字符串可以使用 MSIL 反汇编程序 (ildasm.exe) 查看。

将连接字符串存储在配置文件中

为了避免将连接字符串存储在代码中,可以将代码存储在 ASP.NET 应用程序的 web.config 文件中以及 Windows 应用程序的 app.config 文件中。

连接字符串可以存储在配置文件的 <connectionStrings> 元素中。连接字符串存储为键/值对的形式,可以在运行时使用名称查找存储在 connectionString 属性中的值。以下配置文件示例显示名为 DatabaseConnection 的连接字符串,该连接字符串引用连接到 SQL Server 本地实例的连接字符串。

<connectionStrings>
    <add name="DatabaseConnection" 
        connectionString="Persist Security Info=False;Integrated Security=SSPI;database=Northwind;server=(local);"
         providerName="System.Data.SqlClient" />
</connectionStrings>

从配置文件中检索连接字符串

System.Configuration 命名空间提供使用配置文件中存储的配置信息的类。ConnectionStringSettings 类具有两个属性,映射到上面所示的 <connectionStrings> 示例部分中显示的名称。

ConnectionString

连接字符串。

Name

<connectionStrings> 部分的连接字符串的名称。

Security note安全注意

可以使用受保护的配置可选地加密配置文件中存储的连接字符串。请参见使用受保护的配置加密配置信息对配置节进行加密和解密演练:使用受保护的配置加密配置信息

示例

以下示例通过将连接字符串的名称传递给 ConfigurationManager,再由其返回 ConnectionStringSettings 对象,以便从配置文件中检索连接字符串。ConnectionString 属性用于显示此值。

Visual Basic
Option Explicit On
Option Strict On

Imports System.Configuration

Module Module1
    Sub Main()
        Dim settings As ConnectionStringSettings
        settings = _
           ConfigurationManager.ConnectionStrings("DatabaseConnection")
        If Not settings Is Nothing Then
            Console.WriteLine(settings.ConnectionString)
        End If
    End Sub
End Module
using System;
using System.Configuration;

class Program
{
    static void Main()
    {
        ConnectionStringSettings settings;
        settings = 
            ConfigurationManager.ConnectionStrings["DatabaseConnection"];
        if (settings != null)
        {
            Console.WriteLine(settings.ConnectionString);
        }
    }
}

SqlClient 连接字符串

SqlConnection 的 ConnectionString 属性可以为 SQL Server 7.0 或更高版本的数据库获取或设置连接字符串。如果需要连接到早期版本的 SQL Server,必须使用 OleDb .NET 数据提供程序。

SqlClient 连接字符串语法

连接到 SQL Server 数据库的语法很灵活。下列每个语法形式均将使用集成安全性连接到本地服务器上的 AdventureWorks 数据库。始终通过名称或通过关键字 (local) 指定服务器。

"Persist Security Info=False;Integrated Security=true;Initial Catalog=AdventureWorks;Server=MSSQL1"
"Persist Security Info=False;Integrated Security=SSPI;database=AdventureWorks;server=(local)"
"Persist Security Info=False;Trusted_Connection=True;database=AdventureWorks;server=(local)"

要强制使用某个协议,请添加下列前缀之一:

np:(local), tcp:(local), lpc:(local)

对于 SQL Server 身份验证,使用此语法指定用户名和密码,其中的星号表示有效的用户名和密码。

"Persist Security Info=False;User ID=*****;Password=*****;Initial Catalog=AdventureWorks;Server=MySqlServer"

有关有效的连接字符串关键字的完整列表,请参见 ConnectionString。

连接到命名实例

要连接到 SQL Server 2000 或更高版本的命名实例,请使用 server name\instance name 语法。

Server=MySqlServer\MSSQL1;"

设置网络库

使用此语法通过 IP 地址连接,其中的网络库为 Win32 Winsock TCP/IP,1433 为正在使用的端口(默认值)。

Network Library=dbmssocn;Data Source=000.000.000.000,1433;

SQL Server 在建立连接时允许使用下列网络库。

dbnmpntw

Win32 命名管道

dbmssocn

Win32 Winsock TCP/IP

dbmsspxn

Win32 SPX/IPX

dbmsvinn

Win32 Banyan Vines

dbmsrpcn

Win32 多重协议 (Windows RPC)

OleDb 连接字符串

通过 OleDbConnection 的 ConnectionString 属性可以为 OLE DB 数据源(例如 Microsoft Access 或 SQL Server 6.5 或更低版本)获取或设置连接字符串。对 SQL Server 7.0 或更高版本使用 SqlConnection。

OleDb 连接字符串语法

必须为 OleDbConnection 连接字符串指定提供程序名称。以下连接字符串使用 Jet 提供程序连接到 Microsoft Access 数据库。注意,如果数据库未受保护(默认设置),UserID 和 Password 关键字是可选的。

Provider=Microsoft.Jet.OLEDB.4.0; Data Source=d:\Northwind.mdb;User ID=Admin;Password=; 

如果数据库受保护,必须提供工作组信息文件的位置。

Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\Northwind.mdb;Jet OLEDB:System Database=d:\NorthwindSystem.mdw;User ID=*****;Password=*****;

对于 SQL Server 6.5 或更低版本,请使用 sqloledb 关键字。

Provider=sqloledb;Data Source=MySqlServer;Initial Catalog=pubs;User Id=*****;Password=*****;

不要使用通用数据链接文件

可以在通用数据链接 (UDL) 文件中提供 OleDbConnection 的连接信息;但是,应避免这样做。UDL 文件未加密,会以明文的形式公开连接字符串信息。因为 UDL 文件对应用程序来说是基于外部文件的资源,所以,无法使用 .NET Framework 保护其安全。

连接到 Excel

Microsoft Jet 提供程序用于连接到 Excel 工作簿。在以下连接字符串中,Extended Properties 关键字设置 Excel 特定的属性。“HDR=Yes;”指示第一行中包含列名,而不是数据,“IMEX=1;”通知驱动程序始终将“互混”数据列作为文本读取。注意

Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\MyExcel.xls;Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1""

注意,Extended Properties 所需的双引号必须还要加双引号。

Data Shape 提供程序连接字符串语法

在使用 Microsoft Data Shape 提供程序时,应同时使用 Provider 和 Data Provider 关键字。以下示例使用 Shape 提供程序连接到 SQL Server 的本地实例。

"Provider=MSDataShape;Data Provider=SQLOLEDB;Data Source=(local);Initial Catalog=pubs;Integrated Security=SSPI;" 

Odbc 连接字符串

OdbcConnection 的 ConnectionString 属性可以为 OLE DB 数据源获取或设置连接字符串。以下连接字符串使用 Microsoft 文本驱动程序。

Driver={Microsoft Text Driver (*.txt; *.csv)};DBQ=d:\bin

有关 ODBC 连接字符串语法的更多信息,请参见 ConnectionString。

Oracle 连接字符串

OracleConnection 的 ConnectionString 属性可以为 OLE DB 数据源获取或设置连接字符串。

Data Source=Oracle9i;User ID=*****;Password=*****;

有关 ODBC 连接字符串语法的更多信息,请参见 ConnectionString。

SqlConnection.ConnectionString 属性 

获取或设置用于打开 SQL Server 数据库的字符串。

命名空间:System.Data.SqlClient
程序集:System.Data(在 system.data.dll 中)

语法语法
Visual Basic(声明)
Public Overrides Property ConnectionString As String
Visual Basic(用法)
Dim instance As SqlConnection
Dim value As String

value = instance.ConnectionString

instance.ConnectionString = value
C#
public override string ConnectionString { get; set; }
C++
public:
virtual property String^ ConnectionString {
    String^ get () override;
    void set (String^ value) override;
}
J#
/** @property */
public String get_ConnectionString ()

/** @property */
public void set_ConnectionString (String value)
JScript
public override function get ConnectionString () : String

public override function set ConnectionString (value : String)

属性值

连接字符串,其中包含源数据库名称和建立初始连接所需的其他参数。默认值为空字符串。
异常异常
异常类型 条件

ArgumentException

提供了无效的连接字符串参数,或未提供所需的连接字符串参数。

备注备注

ConnectionString 类似于 OLE DB 连接字符串,但并不相同。与 OLE DB 或 ADO 不同,如果“Persist Security Info”值设置为 false(默认值),则返回的连接字符串与用户设置的 ConnectionString 相同但去除了安全信息。除非将“Persist Security Info”设置为 true,否则,SQL Server .NET Framework 数据提供程序将不会保持,也不会返回连接字符串中的密码。

可以使用 ConnectionString 属性连接到数据库。下面的示例阐释了一个典型的连接字符串。

"Persist Security Info=False;Integrated Security=SSPI;Initial Catalog=Northwind;server=(local)"

使用新的 SqlConnectionStringBuilder 在运行时构造有效的连接字符串。有关更多信息,请参见 Building Connection Strings

只有在连接关闭时才能设置 ConnectionString 属性。许多连接字符串值都具有相应的只读属性。当设置连接字符串时,将更新这些属性(除非检测到错误)。在此情况下,不会更新任何属性。SqlConnection 属性只返回那些包含在 ConnectionString 中的设置。

若要连接到本地计算机,请将服务器指定为“(本地)”。(必须始终指定一个服务器。)

重置已关闭连接上的 ConnectionString 会重置包括密码在内的所有连接字符串值(和相关属性)。例如,如果设置一个连接字符串,其中包含“Database= AdventureWorks”,然后再将该连接字符串重置为“Data Source=myserver;Integrated Security=SSPI”,则 Database 属性将不再设置为“AdventureWorks”。

在设置后会立即分析连接字符串。如果在分析时发现语法中有错误,则产生运行库异常,如 ArgumentException。只有当试图打开连接时,才会发现其他错误。

连接字符串的基本格式包括一系列由分号分隔的关键字/值对。等号 (= ) 连接各个关键字及其值。若要包括含有分号、单引号字符或双引号字符的值,则该值必须用双引号括起来。如果该值同时包含分号和双引号字符,则该值可以用单引号括起来。如果该值以双引号字符开始,则也可以使用单引号。相反,如果该值以单引号开始,也可以使用双引号。如果该值同时包含单引号和双引号字符,则用于将该值括起来的引号字符每次出现时,都必须成对出现。

若要在字符串值中包括前导或尾随空格,则该值必须用单引号或双引号括起来。即使将整数、布尔值或枚举值用引号括起来,其周围的任何前导或尾随空格也将被忽略。然而,保留字符串关键字或值内的空格。使用 .NET Framework 1.1 版或更高版本时,在连接字符串中可以使用单引号或双引号,而不用使用分隔符(例如,Data Source= my'Server 或 Data Source= my"Server),但引号字符不可以为值的第一个或最后一个字符。

若要在关键字或值中包括等号 (=),则它之前必须还有另一个等号。例如,在假设的连接字符串中,

"key==word=value"

关键字是“key=word”并且值是“value”。

如果关键字/值对中的一个特定关键字多次出现在连接字符串中,则将所列出的最后一个用于值集。

关键字不区分大小写。

下表列出了 ConnectionString 中的关键字值的有效名称。

 

关键字

默认值

说明

Application Name

N/A

应用程序的名称,或者“.Net SqlClient Data Provider”(如果不提供应用程序名称)。

Asynch

'false'

如果设置为 true,则启用异步操作支持。可识别的值为 truefalseyesno

AttachDBFilename

- 或 -

extended properties

- 或 -

Initial File Name

N/A

主数据库文件的名称,包括可连接数据库的完整路径名。该路经可以是绝对路径,也可以是相对路径,这取决于是否使用 DataDirectory 替换字符串。如果使用 DataDirectory,则对应的数据库文件必须存在于替换字符串指向的目录的子目录中。

Note注意

远程服务器、HTTP 及 UNC 路径名不受支持。

必须按照如下方式使用关键字“database”(或其别名之一)指定数据库名称:

"AttachDbFileName=|DataDirectory|\data\YourDB.mdf;integrated security=true;database=YourDatabase"

Connect Timeout

- 或 -

Connection Timeout

15

在终止尝试并产生错误之前,等待与服务器的连接的时间长度(以秒为单位)。

Context Connection

'false'

如果应对 SQL Server 进行进程内连接,则为 true

Current Language

N/A

SQL Server 语言记录名称。

Data Source

- 或 -

Server

- 或 -

Address

- 或 -

Addr

- 或 -

Network Address

N/A

要连接的 SQL Server 实例的名称或网络地址。可以在服务器名称之后指定端口号:

server=tcp:servername, portnumber

指定本地实例时,始终使用 (local)。若要强制使用某个协议,请添加下列前缀之一:

np:(local), tcp:(local), lpc:(local)

Encrypt

'false'

当该值为 true 时,如果服务器端安装了证书,则 SQL Server 将对所有在客户端和服务器之间传送的数据使用 SSL 加密。可识别的值为 truefalseyesno

Enlist

'false'

true 表明 SQL Server 连接池程序在创建线程的当前事务上下文中自动登记连接。

Failover Partner

N/A

在其中配置数据库镜像的故障转移合作伙伴服务器的名称。

.NET Framework 1.0 或 1.1 版不支持 Failover Partner 关键字。

Initial Catalog

- 或 -

Database

N/A

数据库的名称。

Integrated Security

- 或 -

Trusted_Connection

'false'

当为 false 时,将在连接中指定用户 ID 和密码。当为 true 时,将使用当前的 Windows 帐户凭据进行身份验证。

可识别的值为 truefalseyesno 以及与 true 等效的 sspi(强烈推荐)。

MultipleActiveResultSets

'true'

如果为 true,则应用程序可以维护多活动结果集 (MARS)。如果为 false,则应用程序必须在执行该连接上的任何其他批处理之前处理或取消一个批处理中的多个结果集。

可识别的值为 truefalse

.NET Framework 1.0 或 1.1 版不支持该关键字。

Network Library

- 或 -

Net

'dbmssocn'

用于建立与 SQL Server 实例的连接的网络库。支持的值包括 dbnmpntw(命名管道)、dbmsrpcn(多协议)、dbmsadsn (Apple Talk)、dbmsgnet (VIA)、dbmslpcn(共享内存)及 dbmsspxn (IPX/SPX) 和 dbmssocn (TCP/IP)。

相应的网络 DLL 必须安装在要连接的系统上。如果不指定网络而使用一个本地服务器(比如“.”或“(local)”),则使用共享内存。

Packet Size

8192

用来与 SQL Server 的实例进行通信的网络数据包的大小,以字节为单位。

Password

- 或 -

Pwd

N/A

SQL Server 帐户登录的密码。建议不要使用。为保持高安全级别,我们强烈建议您使用 Integrated SecurityTrusted_Connection 关键字。

Persist Security Info

'false'

当该值设置为 falseno(强烈推荐)时,如果连接是打开的或者一直处于打开状态,那么安全敏感信息(如密码)将不会作为连接的一部分返回。重置连接字符串将重置包括密码在内的所有连接字符串值。可识别的值为 truefalseyesno

Replication

'false'

如果使用连接来支持复制,则为 true

TrustServerCertificate

'false'

如果设置为 true,则使用 SSL 对通道进行加密,但不通过证书链对可信度进行验证。如果将 TrustServerCertificate 设置为 true 并将 Encrypt 设置为 false,则不对通道进行加密。可识别的值为 truefalseyesno。有关更多信息,请参见 SQL Server 2005 Books Online(《SQL Server 2005 联机丛书》)中的“Encryption Hierarchy”(加密层次结构)和“Using Encryption Without Validation”(使用不验证的加密)。

Type System Version

N/A

指示应用程序期望的类型系统的字符串值。可能的值有:

Type System Version=SQL Server 2000;

Type System Version=SQL Server 2005;

Type System Version=Latest;

如果设置为 SQL Server 2000,将使用 SQL Server 2000 类型系统。与 SQL Server 2005 实例连接时,执行下列转换:

XML 到 NTEXT

UDT 到 VARBINARY

VARCHAR(MAX)、NVARCHAR(MAX) 和 VARBINARY(MAX) 分别到 TEXT、NEXT 和 IMAGE。

如果设置为 SQL Server 2005,将使用 SQL Server 2005 类型系统。对 ADO.NET 的当前版本不进行任何转换。

如果设置为 Latest,将使用此客户端-服务器对无法处理的最新版本。这个最新版本将随着客户端和服务器组件的升级自动更新。

User ID

N/A

SQL Server 登录帐户。建议不要使用。为保持高安全级别,我们强烈建议您使用 Integrated SecurityTrusted_Connection 关键字。

User Instance

'false'

一个值,用于指示是否将连接从默认的 SQL Server 速成版实例重定向到调用方帐户下运行的运行时启动的实例。

Workstation ID

本地计算机名称

连接到 SQL Server 的工作站的名称。

下表列出了 ConnectionString 内连接池值的有效名称。有关更多信息,请参见 使用连接池

 

名称

默认值

说明

Connection Lifetime

0

当连接被返回到池时,将其创建时间与当前时间作比较,如果时间长度(以秒为单位)超出了由 Connection Lifetime 指定的值,该连接就会被销毁。这在聚集配置中很有用(用于强制执行运行中的服务器和刚置于联机状态的服务器之间的负载平衡)。

零 (0) 值将使池连接具有最大的连接超时。

Connection Reset

'true'

确定从池中提取数据库连接时是否重置数据库连接。对于 SQL Server 7.0 版,设置为 false 可避免获取连接时再有一次额外的服务器往返行程,但须注意此时并未重置连接状态(如数据库上下文)。

只要不将 Connection Reset 设置为 false,连接池程序就不会受到 ChangeDatabase 方法的影响。连接在退出相应的连接池以后将被重置,并且服务器将移回登录时数据库。不会创建新的连接,也不会重新进行身份验证。如果将 Connection Reset 设置为 false,则池中可能会产生不同数据库的连接。

Enlist

'true'

当该值为 true 时,池程序在创建线程的当前事务上下文中自动登记连接。可识别的值为 truefalseyesno

Load Balance Timeout

0

连接被销毁前在连接池中生存的最短时间(以秒为单位)。

Max Pool Size

100

池中允许的最大连接数。

Min Pool Size

0

池中允许的最小连接数。

Pooling

'true'

当该值为 true 时,系统将从适当的池中提取 SQLConnection 对象,或在需要时创建该对象并将其添加到适当的池中。可识别的值为 truefalseyesno

当设置需要布尔值的关键字或连接池值时,您可以使用“yes”代替“true”,用“no”代替“false”。整数值表示为字符串。

Note注意

SQL Server .NET Framework 数据提供程序使用它自己的协议与 SQL Server 进行通信。因此,当连接到 SQL Server 时,它不支持 ODBC 数据源名称 (DSN) 的使用,因为它不添加 ODBC 层。

Caution note警告

在此版本中,在应用程序中根据用户输入构造连接字符串时(例如,从对话框中检索用户 ID 和密码信息并将其追加到连接字符串时)应相当谨慎。应用程序应确保用户无法在这些值中嵌入其他连接字符串参数(例如,输入“validpassword;database=somedb”作为密码,以试图连接到其他数据库)。

示例示例

下面的示例创建 SqlConnection 并在打开连接前设置 ConnectionString 属性。

Visual Basic
Private Sub OpenSqlConnection()
    Dim connectionString As String = GetConnectionString()

    Using connection As New SqlConnection()

        connection.ConnectionString = connectionString

        connection.Open()

        Console.WriteLine("State: {0}", connection.State)
        Console.WriteLine("ConnectionString: {0}", _
            connection.ConnectionString)
    End Using
End Sub

Private Function GetConnectionString() As String
    ' To avoid storing the connection string in your code,  
    ' you can retrieve it from a configuration file, using the
    ' System.Configuration.ConfigurationSettings.AppSettings property
    Return "Data Source=(local);Database=AdventureWorks;" _
      & "Integrated Security=SSPI;"
End Function
private static void OpenSqlConnection()
{
    string connectionString = GetConnectionString();

    using (SqlConnection connection = new SqlConnection())
    {
        connection.ConnectionString = connectionString;

        connection.Open();

        Console.WriteLine("State: {0}", connection.State);
        Console.WriteLine("ConnectionString: {0}",
            connection.ConnectionString);
    }
}

static private string GetConnectionString()
{
    // To avoid storing the connection string in your code, 
    // you can retrieve it from a configuration file, using the 
    // System.Configuration.ConfigurationSettings.AppSettings property 
    return "Data Source=(local);Initial Catalog=AdventureWorks;"
        + "Integrated Security=SSPI;";
}
使用连接事件 

所有 .NET Framework 数据提供程序中的 Connection 对象有两个事件,可用于从数据源中检索信息性消息或确定 Connection 的状态是否已被更改。下表描述 Connection 对象的这些事件。

 
事件 说明

InfoMessage

当从数据源中返回信息性消息时发生。信息性消息是数据源中不会引发异常的消息。

StateChange

当 Connection 的状态改变时发生。

使用 InfoMessage 事件

可以使用 SqlConnection 对象的 InfoMessage 事件从数据源中检索警告和信息性消息。从数据源返回的严重程度为 11 到 16 的错误将引发异常。但是,InfoMessage 事件可用于从数据源中获取与错误无关联的消息。对于 Microsoft SQL Server,任何严重程度等于或小于 10 的错误都将被视为信息性消息,将使用 InfoMessage 事件来捕获。有关更多信息,请参见“SQL Server 联机图书”中的“错误消息严重程度”主题。

InfoMessage 事件接收 SqlInfoMessageEventArgs 对象,该对象在其 Errors 属性中包含来自数据源的消息的集合。您可以查询此集合中的 Error 对象,以获取错误编号和消息文本以及错误的来源。SQL Server .NET Framework 数据提供程序还包含有关消息所来自的数据库、存储过程和行号的详细信息。

示例

以下代码示例显示如何为 InfoMessage 事件添加事件处理程序。

Visual Basic
' Assumes that connection represents a SqlConnection object.
  AddHandler connection.InfoMessage, _
    New SqlInfoMessageEventHandler(AddressOf OnInfoMessage)

Private Shared Sub OnInfoMessage(sender As Object, _
  args As SqlInfoMessageEventArgs)
  Dim err As SqlError
  For Each err In args.Errors
    Console.WriteLine("The {0} has received a severity {1}, _
       state {2} error number {3}\n" & _
      "on line {4} of procedure {5} on server {6}:\n{7}", _
      err.Source, err.Class, err.State, err.Number, err.LineNumber, _
    err.Procedure, err.Server, err.Message)
  Next
End Sub
// Assumes that connection represents a SqlConnection object.
  connection.InfoMessage += 
    new SqlInfoMessageEventHandler(OnInfoMessage);

protected static void OnInfoMessage(
  object sender, SqlInfoMessageEventArgs args)
{
  foreach (SqlError err in args.Errors)
  {
    Console.WriteLine(
  "The {0} has received a severity {1}, state {2} error number {3}\n" +
  "on line {4} of procedure {5} on server {6}:\n{7}",
   err.Source, err.Class, err.State, err.Number, err.LineNumber, 
   err.Procedure, err.Server, err.Message);
  }
}

将错误作为信息性消息处理

通常,只有从服务器发出的信息性消息和警告消息才会触发 InfoMessage 事件。但是,真正的错误发生时,启动服务器操作的 ExecuteNonQuery 或 ExecuteReader 方法将暂停执行,并引发异常。

如果无论服务器生成任何错误都要继续处理命令中的语句的其他部分,请将 SqlConnection 的 FireInfoMessageEventOnUserErrors 属性设置为 true。这样做会使连接对错误触发 InfoMessage 事件,而不是引发异常并中断处理。客户端应用程序可以处理此事件并对错误情况做出响应。

Note注意

严重程度等于或大于 17 的错误会造成服务器停止处理命令,这种错误必须作为异常来处理。在这种情况下,无论如何在 InfoMessage 事件中处理该错误,都会引发异常。

使用 StateChange 事件

StateChange 事件在 Connection 的状态改变时发生。StateChange 事件接收 StateChangeEventArgs,使您能够使用 OriginalState 和 CurrentState 属性来确定 Connection 状态的改变。OriginalState 属性是一个 ConnectionState 枚举,指示改变前的 Connection 状态。CurrentState 是一个 ConnectionState 枚举,指示改变后的 Connection 状态。

以下代码示例在 Connection 的状态改变时使用 StateChange 事件将消息写入控制台。

Visual Basic
' Assumes connection represents a SqlConnection object.
  AddHandler connection.StateChange, _
    New StateChangeEventHandler(AddressOf OnStateChange)

Protected Shared Sub OnStateChange( _
  sender As Object, args As StateChangeEventArgs)

  Console.WriteLine( _
  "The current Connection state has changed from {0} to {1}.", _
  args.OriginalState, args.CurrentState)
End Sub
// Assumes connection represents a SqlConnection object.
  connection.StateChange  += new StateChangeEventHandler(OnStateChange);

protected static void OnStateChange(object sender, 
  StateChangeEventArgs args)
{
  Console.WriteLine(
    "The current Connection state has changed from {0} to {1}.",
      args.OriginalState, args.CurrentState);
}
了解连接池 

池连接可以显著提高应用程序的性能和可缩放性。.NET Framework 数据提供程序处理连接池的方式有所不同。有关 SQL Server 的连接池的信息,请参阅 使用连接池

OLE DB .NET Framework 数据提供程序连接池

OLE DB .NET Framework 数据提供程序使用 OLE DB 会话池自动管理连接池。连接字符串参数可用于启用或禁用包括池在内的 OLE DB 服务。例如,以下连接字符串禁用 OLE DB 会话池和自动事务登记。

Provider=SQLOLEDB;OLE DB Services=-4;Data Source=localhost;Integrated Security=SSPI;

我们建议在使用完连接时一定要关闭或断开连接,以便连接可以返回池。不是显式关闭的连接可能无法返回池。例如,如果连接已超出范围但没有显式关闭,则仅当达到最大池大小而该连接仍然有效时,该连接才会返回到连接池中。

有关 OLE DB 会话池或资源池以及如何通过重写 OLE DB 提供程序服务默认值禁用池的更多信息,请参见 MSDN 库中的 OLE DB Programmer's Reference

ODBC .NET Framework 数据提供程序的连接池

ODBC .NET Framework 数据提供程序的连接池由用于该连接的 ODBC 驱动程序管理器管理,不受 ODBC .NET Framework 数据提供程序的影响。

要启用或禁用连接池,在“控制面板”的“管理工具”文件夹中打开“ODBC 数据源管理器”。通过“连接池”选项卡可以为每个已安装的 ODBC 驱动程序指定连接池参数。请注意,对特定 ODBC 驱动程序所做的更改会影响所有使用该 ODBC 驱动程序的应用程序。

有关 ODBC 连接池的更多信息,请参见 MSDN 库中的 OLE DB Programmer's Reference

Oracle .NET Framework 数据提供程序连接池

Oracle .NET Framework 数据提供程序自动为 ADO.NET 客户端应用程序提供连接池。您也可以提供几个连接字符串修饰符,用于控制连接池的行为(请参见本主题后文的“使用连接字符串关键字控制连接池”)。

池的创建和分配

当连接打开时,将根据一种精确的匹配算法来创建连接池,该算法会使连接池与连接中的字符串相关联。每个连接池都与一个不同的连接字符串相关联。当新连接打开时,如果连接字符串不精确匹配现有池,则将创建一个新池。

连接池一旦创建,直到活动进程终止时才会被毁坏。维护不活动的池或空池占用的系统资源非常少。

连接的添加

连接池是为每个唯一的连接字符串创建的。当创建一个池后,将创建多个连接对象并将其添加到该池中,以满足最小池大小的要求。连接将根据需要添加到池中,直至达到最大池大小。

在请求 OracleConnection 对象时,如果存在可用的连接,则将从池中获取该对象。要成为可用连接,该连接当前必须未被使用,具有匹配的事务上下文或者不与任何事务上下文相关联,并且具有与服务器的有效链接。

如果已达到最大池大小且不存在可用的连接,则该请求将会排队。当连接被释放回池中时,连接池管理程序通过重新分配连接来满足这些请求。连接在关闭或断开时释放回池中。

连接的移除

如果连接长时间空闲,或池进程检测到与服务器的连接已断开,连接池进程会将该连接从池中移除。请注意,只有在尝试与服务器进行通信后,才可以检测到这种情况。如果发现某连接不再连接到服务器,则会将其标记为无效。连接池管理程序会定期扫描连接池,查找已释放到池中并标记为无效的对象。找到后,这些连接将被永久移除。

如果存在一个与已消失的服务器的连接,如果连接池进程尚未检测到断开的连接并将连接标记为无效,可以从池中提取此连接。当发生这种情况时,将生成异常。但是,为了将该连接释放回池中,仍必须将其关闭。

不要在类的 Finalize 方法中对 Connection、DataReader 或任何其他托管对象调用 Close 或 Dispose。在终结器中,仅释放类直接拥有的非托管资源。如果类不拥有任何非托管资源,则不要在类定义中包含 Finalize 方法。有关更多信息,请参见垃圾回收

事务支持

连接是根据事务上下文来从池中取出并进行分配的。请求线程和所分配的连接的上下文必须匹配。因此,每个连接池实际上又分为不具有关联事务上下文的连接以及 N 个各自包含与一个特定事务上下文的连接的子部分。

当连接关闭时,它将被释放回池中,并根据其事务上下文放入相应的子部分。因此,即使分布式事务仍然挂起,仍可以关闭该连接而不会生成错误。这样,您就可以在随后提交或中止分布式事务。

使用连接字符串关键字控制连接池

OracleConnection 对象的 ConnectionString 属性支持连接字符串键/值对,可以用于调整连接池逻辑的行为。

下表描述了可用于调整连接池行为的 ConnectionString 值。

 
名称 默认值 说明

Connection Lifetime

0

连接返回到池中后,创建时间将与当前时间进行比较,如果时间跨度(秒)超过 Connection Lifetime 指定的值,该连接将被破坏。在聚集配置中可以使用它来强制在运行服务器和刚联机的服务器之间达到负载平衡。

如果值为零 (0),则将使池连接具有最大的超时期限。

Enlist

'true'

当为 true 时,如果存在事务上下文,池管理程序将自动在创建线程的当前事务上下文中登记连接。

Max Pool Size

100

池中允许的最大连接数。

Min Pool Size

0

池中维护的最小连接数。

Pooling

'true'

当为 true 时,将从相应的池中取出连接,或者在必要时创建连接并将其添加到相应的池中。

使用连接池 

连接到数据库服务器通常由几个需要很长时间的步骤组成。必须建立物理通道(例如套接字或命名管道),必须与服务器进行初次握手,必须分析连接字符串信息,必须由服务器对连接进行身份验证,必须运行检查以便在当前事务中登记,等等。

实际上,大多数应用程序仅使用一个或几个不同的连接配置。这意味着在执行应用程序期间,许多相同的连接将反复地打开和关闭。为了使打开的连接成本最低,ADO.NET 使用称为连接池的优化方法。

连接池减少新连接需要打开的次数。池进程保持物理连接的所有权。通过为每个给定的连接配置保留一组活动连接来管理连接。只要用户在连接上调用 Open,池进程就会检查池中是否有可用的连接。如果某个池连接可用,会将该连接返回给调用者,而不是打开新连接。应用程序在该连接上调用 Close 时,池进程会将连接返回到活动连接池集中,而不是真正关闭连接。连接返回到池中之后,即可在下一个 Open 调用中重复使用。

只有配置相同的连接可以建立池连接。ADO.NET 同时保留多个池,每个配置一个池。连接由连接字符串以及 Windows 标识(在使用集成的安全性时)分为多个池。

池连接可以大大提高应用程序的性能和可缩放性。默认情况下,ADO.NET 中启用连接池。除非显式禁用,否则,连接在应用程序中打开和关闭时,池进程将对连接进行优化。还可以提供几个连接字符串修饰符来控制连接池的行为。有关更多信息,请参见本主题后面的“使用连接字符串关键字控制连接池”。

池的创建和分配

在初次打开连接时,将根据完全匹配算法创建连接池,该算法将池与连接中的连接字符串关联。每个连接池与不同的连接字符串关联。打开新连接时,如果连接字符串并非与现有池完全匹配,将创建一个新池。按进程、按应用程序域、按连接字符串以及(在使用集成的安全性时)按 Windows 标识来建立池连接。

在以下 C# 示例中创建了三个新的 SqlConnection 对象,但是管理时只需要两个连接池。注意,根据为 Initial Catalog 分配的值,第一个和第二个连接字符串有所不同。

using (SqlConnection connection = new SqlConnection(
  "Integrated Security=SSPI;Initial Catalog=Northwind"))
    {
        connection.Open();      
        // Pool A is created.
    }

using (SqlConnection connection = new SqlConnection(
  "Integrated Security=SSPI;Initial Catalog=pubs"))
    {
        connection.Open();      
        // Pool B is created because the connection strings differ.
    }

using (SqlConnection connection = new SqlConnection(
  "Integrated Security=SSPI;Initial Catalog=Northwind"))
    {
        connection.Open();      
        // The connection string matches pool A.
    }

如果 MinPoolSize 在连接字符串中未指定或指定为零,池中的连接将在一段时间不活动后关闭。但是,如果指定的 MinPoolSize 大于零,在 AppDomain 被卸载并且进程结束之前,连接池不会被破坏。非活动或空池的维护只需要最少的系统开销。

Note注意

如果发生致命错误(例如故障转移或注册表中的别名更改),池将自动清除。

添加连接

连接池是为每个唯一的连接字符串创建的。当创建一个池后,将创建多个连接对象并将其添加到该池中,以满足最小池大小的要求。连接根据需要添加到池中,但是不能超过指定的最大池大小(默认值为 100)。连接在关闭或断开时释放回池中。

在请求 SqlConnection 对象时,如果存在可用的连接,将从池中获取该对象。连接要可用,必须未使用,具有匹配的事务上下文或未与任何事务上下文关联,并且具有与服务器的有效链接。

连接池进程通过在连接释放回池中时重新分配连接,来满足这些连接请求。如果已达到最大池大小且不存在可用的连接,则该请求将会排队。然后,池进程尝试重新建立任何连接,直到到达超时时间(默认值为 15 秒)。如果池进程在连接超时之前无法满足请求,将引发异常。

Caution note警告

我们建议您在使用完连接时一定要关闭连接,以便连接可以返回池。要关闭连接,可以使用 Connection 对象的 Close 或 Dispose 方法,也可以通过在 C# 的 using 语句中或在 Visual Basic 的 Using 语句中打开所有连接。不是显式关闭的连接可能不会添加或返回到池中。例如,如果连接已超出范围但没有显式关闭,则仅当达到最大池大小而该连接仍然有效时,该连接才会返回到连接池中。有关更多信息,请参见 Visual Basic 的using 语句(C# 参考)如何:释放系统资源

Note注意

不要在类的 Finalize 方法中对 Connection、DataReader 或任何其他托管对象调用 Close 或 Dispose。在终结器中,仅释放类直接拥有的非托管资源。如果类不拥有任何非托管资源,则不要在类定义中包含 Finalize 方法。有关更多信息,请参见垃圾回收

移除连接

连接池进程定期扫描连接池,查找没有通过 Close 或 Dispose 关闭的未用连接,并重新建立找到的连接。如果应用程序没有显式关闭或断开其连接,连接池进程可能需要很长时间才能重新建立连接,所以,最好确保在连接中显式调用 Close 和 Dispose。

如果连接长时间空闲,或池进程检测到与服务器的连接已断开,连接池进程会将该连接从池中移除。注意,只有在尝试与服务器进行通信之后才能检测到断开的连接。如果发现某连接不再连接到服务器,则会将其标记为无效。无效连接只有在关闭或重新建立后,才会从连接池中移除。

如果存在与已消失的服务器的连接,那么即使连接池管理程序未检测到已断开的连接并将其标记为无效,仍有可能将此连接从池中取出。这种情况是因为检查连接是否仍有效的系统开销将造成与服务器的另一次往返,从而抵消了池进程的优势。发生此情况时,初次尝试使用该连接将检测连接是否曾断开,并引发异常。

清除池

ADO.NET 2.0 引入了两种新的方法来清除池:ClearAllPoolsClearPool。ClearAllPools 清除给定提供程序的连接池,ClearPool 清除与特定连接关联的连接池。如果在调用时连接正在使用,将进行相应的标记。连接关闭时,将被丢弃,而不是返回池中。

事务支持

连接是根据事务上下文来从池中取出并进行分配的。除非在连接字符串中指定了 Enlist=false,否则,连接池将确保连接在 Current 上下文中登记。如果连接使用登记的 System.Transactions 事务关闭并返回池中,连接将保留在池中,以便使用相同 System.Transactions 事务对该连接池的下一次请求将返回相同的连接。如果该事务没有可用连接,在该连接打开时,将自动注册该连接。

当连接关闭时,它将被释放回池中,并根据其事务上下文放入相应的子部分。因此,即使分布式事务仍然挂起,仍可以关闭该连接而不会生成错误。这样,您就可以在随后提交或中止分布式事务。

使用连接字符串关键字控制连接池

SqlConnection 对象的 ConnectionString 属性支持连接字符串键/值对,可以用于调整连接池逻辑的行为。有关更多信息,请参见 ConnectionString

池碎片

池碎片是许多 Web 应用程序中的一个常见问题,应用程序可能会创建大量在进程退出后才会释放的池。这样,将打开大量的连接,占用许多内存,从而影响性能。

因为集成安全性产生的池碎片

连接根据连接字符串以及用户标识来建立池连接。因此,如果使用网站上的基本身份验证或 Windows 身份验证以及集成的安全登录,每个用户将获得一个池。尽管这样可以提高单个用户的后续数据库请求的性能,但是该用户无法利用其他用户建立的连接。这样还使每个用户至少产生一个与数据库服务器的连接。这对特定 Web 应用程序结构会产生副作用,因为开发人员需要衡量安全性和审计要求。

因为许多数据库产生的池碎片

许多 Internet 服务提供商在一台服务器上托管多个网站。他们可能使用单个数据库确认窗体身份验证登录,然后为该用户或用户组打开与特定数据库的连接。与身份验证数据库的连接将建立池连接,供每个用户使用。但是,每个数据库的连接存在一个独立的池,因此增加了与服务器的连接数。

这也会对应用程序设计产生副作用。但是,可以通过一个相对简单的方式避免此副作用,而又不会影响连接 SQL Server 时的安全性。不是为每个用户或组连接独立的数据库,而是连接到服务器上的相同数据库,然后执行 Transact-SQL USE 语句来切换为所需的数据库。以下代码段演示入如何创建与 master 数据库的初始连接,然后切换到 databaseName 字符串变量中指定的所需数据库。

Visual Basic
' Assumes that command is a valid SqlCommand object.
Using connection As New SqlConnection( _
  "Server=MSSQL1;uid=xxx;pwd=xxx;database=master")
    connection.Open()
    command.ExecuteNonQuery("USE " & databaseName)
End Using
// Assumes that command is a SqlCommand object.
using (SqlConnection connection = new SqlConnection(
  "Server=MSSQL1;uid=xxx;pwd=xxx;database=master"))
  {
    connection.Open();
    command.ExecuteNonQuery("USE " + databaseName);
  }

应用程序角色和连接池

通过调用 sp_setapprole 系统存储过程激活了 SQL Server 应用程序角色之后,该连接的安全上下文无法重置。但是,如果启用了池,连接将返回池,在重复使用池连接时会出错。

如果使用的是 SQL Server 应用程序角色,我们建议您在连接字符串中为应用程序禁用连接池。有关更多信息,请参见知识库文章“SQL application role errors with OLE DB resource pooling”。

posted @ 2006-11-20 15:50  疯一样的自由  阅读(2488)  评论(0编辑  收藏  举报