连接到ADO.NET中的数据源

在 ADO.NET 中,通过在连接字符串中提供必要的身份验证信息,使用 Connection 对象连接到特定的数据源。使用的 Connection 对象取决于数据源的类型。随 .NET Framework 提供的每个 .NET Framework 数据提供程序都具有一个 DbConnection 对象,适用于 SQL Server的.NET Framework 数据提供程序包括一个 SqlConnection 对象。

建立连接

要连接到 Microsoft SQL Server , 请使用 SQL Server .NET Framework 数据提供程序的 SqlConnection 对象。

关闭连接

在使用完连接时一定要关闭连接,以便连接可以返回池。如果在 C# 代码中存在 Using 块,将自动断开连接,即使发生无法处理的异常。也可以使用适合所使用的提供程序的连接对象的 Close 或 Dispose 方法。不是显式关闭的连接可能不会添加或返回到池中。例如,如果连接已超出范围但没有显式关闭,则仅当达到最大池大小 而该连接仍然有效时,该连接才会返回到连接池中。

注意

不要在类的Finalize方法中对 Connection、DataReader 或任何其他托管对象调用 Close 或 Dispose 。在终结器中,仅释放类直接拥有的非托管资源。如果类不拥有任何非托管资源,则不要在类定义中包含 Finalize 方法。

注意

从连接池中获取连接或将连接返回到连接池中时,服务器上不会引发登录和注销事件,这是因为在将连接返回到连接池时实际上并没有将其关闭。

连接到SQL Server

以下代码示例演示如何创建并打开与SQL Server数据库的连接。

using (var connection = new SqlConnection(ConnectionStr))
{
connection.Open();
}

连接事件

使用 StateChange 事件

StateChange 事件在 Connection 的状态改变时发生。 StateChange 事件接收 StateChangeEventArgs,使能够使用 OriginalState 和 CurrentState 属性来确定 Connection 状态的改变。

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

connection.StateChange += connection_StateChange;

static void connection_StateChange(object sender, StateChangeEventArgs e)
{
Console.WriteLine("The current Connection state has changed from {0} to {1}.", e.OriginalState, e.CurrentState);
}

在 ADO.NET 中的连接字符串

连接字符串包含作为参数从数据提供程序传递到数据源的初始化信息。其语法取决于数据提供程序,并且会在试图打开连接的过程中对连接字符串进行分析。语法错误会生成运行时异常,但其他错误只有在数据源收到信息后才会发生。经过验证后,数据源将应用连接字符串中指定的选项并打开连接。

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

keyword1=value; keyword2=value;

关键字不区分大小写,并将忽略键/值对之间的空格。不过,根据数据源的不同,值可能是区分大小写的。任何包含分号、单引号或双引号的值必须用双引号引起来。

连接字符串生成器

连接字符串生成器旨在排除推测,防止出现语法错误和安全漏洞。

下面的示例演示SqlConnectionBuilder如何处理为Initial Catalog设置插入的额外值。

 var builder = new SqlConnectionStringBuilder();
builder.DataSource = "(local)";
builder.IntegratedSecurity = true;
builder.InitialCatalog = "AdventureWorks;NewValue=Bad"; Console.WriteLine(builder.ConnectionString);

输出结果表明,通过用双引号转义该额外值而不作为新的键/值对将其追加到连接字符串,SqlConnectionStringBuilder可以正确处理此额外值。

Data Source=(local);Initial Catalog="AdventureWorks;NewValue=Bad";Integrated Security=True

使用外部配置文件

外部配置文件是单独的文件,此类文件包含由一部分组成的配置文件的片段。外部配置文件由主配置文件引用。如果在部署完应用程序后连接字符串可能会被编辑,那么将connectionStrings节存储在物理上独立的文件中会很有用。

若要将连接字符串存储在外部配置文件中,请创建一个只包含connectionStrings节的单独的文件。不要包含任何其他的元素、节或属性。此示例演示外部配置文件的语法。

<connectionStrings>
<add name="SQLServerConnectionString"
connectionString="server=DTSZOPAULHUANG\SQLEXPRESS;initial catalog=TSQLFundamentals2008;integrated security=true"
providerName="System.Data.SqlClient"/>
</connectionStrings>

在主应用程序配置文件中,可以使用configSource属性指定外部文件的完全限定名和位置,此示例引用名为connections.config的外部配置文件。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup> <connectionStrings configSource="connections.config"></connectionStrings>
</configuration>

连接字符串语法

Windows身份验证

建议使用Windows身份验证(有时也称为"集成安全性")连接到支持其的数据源。连接字符串中使用的语法根据提供程序的不同而不同。下面演示 SQL Server .NET Framework 数据提供程序的 Windows 身份验证语法。

Integrated Security=true;
//or
Integrated Security=SSPI;

下列语法使用 Windows 身份验证连接到特定的数据库。

connectionString="server=DTSZOPAULHUANG\SQLEXPRESS;initial catalog=TSQLFundamentals2008;integrated security=true" 
SQL Server  登录

Windows 身份验证是用于连接到 SQL Server 的首选方法。但是,如果需要 SQL Server 身份验证,请使用下列语法来指定用户名和密码。

connectionString="server=DTSZOPAULHUANG\SQLEXPRESS;initial catalog=TSQLFundamentals2008;User ID=****;Password=****;Persist Security Info=False"

安全性注意

Persist Security Info 关键字的默认设置为 false .如果将其设置为 true ,则允许在打开连接后通过连接获取安全敏感信息(包括用户 ID 和密码)。保持将 Persist Securiy Info 设置为 false ,以确保不受信任的来源不能访问敏感的连接字符串信息。

注意

Windows 身份验证优先于 SQL Server 登录。如果同时指定 Integrated Securiy=true 以及用户名和密码,将忽略用户名和密码,而使用 Windows 身份验证。

SQL Sever 连接池

概述

连接到数据源可能需要很长时间。为了最大程度地降低打开连接的成本,ADO.NET 使用一种称为连接池的优化技术,这种技术可最大程度地降低重复打开和关闭连接所造成的成本。

连接到数据库服务器通常由几个需要很长时间的步骤组成。必须建立物理通道,必须与服务器进行初次握手,必须分析连接字符串信息,必须由服务器对连接进行身份验证等等。

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

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

只有配置相同的连接可以建立池连接。ADO.NET 同时保留多个池,每种配置各一个。在使用集成的安全性时,连接按照连接字符串以及 Windows 标识分到多个池中。还根据连接是否已在事务中登记来建立池连接。池连接可以显著提高应用程序的性能和可缩放性。默认情况下,在 ADO.NET 中启用连接池,除非显式禁用。

为了比较形象的比较在打开及关闭连接池时的效果,下面进行示例演示。示例1是默认打开连接池进行多次数据库操作情况下的耗时情况,示例2是主动关闭连接池后对应的耗时情况。

示例1:

<connectionStrings>
<add name="SQLServerConnectionString"
connectionString="server=DTSZOPAULHUANG\SQLEXPRESS;initial catalog=TSQLFundamentals2008;Integrated Security=true;"
providerName="System.Data.SqlClient"/>
</connectionStrings>
    public static class DataAccess
{ private static string _connectionString = null; public static int ExecuteNonQuerySql(string sql, SqlParameter[] sqlParameters = null)
{
_connectionString = ConfigurationManager.ConnectionStrings["SQLServerConnectionString"].ConnectionString; using (var connection = new SqlConnection(_connectionString))
{
//connection.StateChange += connection_StateChange; var commmand = connection.CreateCommand(); commmand.CommandType = CommandType.Text;
commmand.CommandText = sql;
if (sqlParameters != null)
{
commmand.Parameters.AddRange(sqlParameters);
} Stopwatch stopwatch = new Stopwatch();
stopwatch.Start(); connection.Open(); Console.WriteLine(stopwatch.ElapsedMilliseconds); return commmand.ExecuteNonQuery();
}
}
}
        private void btnUpdate_Click(object sender, EventArgs e)
{
string sql = "UPDATE Sales.Shippers SET CompanyName = @CompanyName, Phone = @Phone WHERE ShipperId = @ShipperId"; var sqlParameters = new List<SqlParameter>(); sqlParameters.Add(new SqlParameter("CompanyName", "SML"));
sqlParameters.Add(new SqlParameter("Phone", ""));
sqlParameters.Add(new SqlParameter("ShipperId", )); int result = DataAccess.ExecuteNonQuerySql(sql, sqlParameters.ToArray()); MessageBox.Show(result.ToString());
}

//测试结果

示例2:修改连接字符串,使之禁用连接池,其他部分均不变动。

<connectionStrings>
<add name="SQLServerConnectionString"
connectionString="server=DTSZOPAULHUANG\SQLEXPRESS;initial catalog=TSQLFundamentals2008;Integrated Security=true;Pooling=False"
providerName="System.Data.SqlClient"/>
</connectionStrings>

//测试结果

池的创建和分配

在初次打开连接时,将根据完全匹配算法创建连接池,该算法将池与连接中的连接字符串关联。按进程、应用程序域、连接字符串以及 Windows 标识(在使用集成的安全性时)来建立池连接。连接字符串还必须是完全匹配的;按不同顺序为同一连接提供的关键字将分到单独的池中。

在以下的示例中创建了三个新的 SqlConnection 对象,但是管理时只需要两个连接池。注意连接字符串的不同,可以通过查看 connection 对象的 ClientConnectionId 属性查看连接的 ID。

    public class Testing
{
public void Test()
{
using (SqlConnection connection = new SqlConnection(
@"server=DTSZOPAULHUANG\SQLEXPRESS;initial catalog=TSQLFundamentals2008;Integrated Security=true;"))
{
connection.Open();
// Pool A is created.
Console.WriteLine(connection.ClientConnectionId);
} using (SqlConnection connection = new SqlConnection(
@"server=DTSZOPAULHUANG\SQLEXPRESS;initial catalog=TSQLFundamentals2008;Integrated Security=SSPI;"))
{
connection.Open();
// Pool B is created because the connection strings differ.
Console.WriteLine(connection.ClientConnectionId);
} using (SqlConnection connection = new SqlConnection(
@"server=DTSZOPAULHUANG\SQLEXPRESS;initial catalog=TSQLFundamentals2008;Integrated Security=true;"))
{
connection.Open();
// The connection string matches pool A.
Console.WriteLine(connection.ClientConnectionId);
}
}
}

//测试结果

从结果可以清楚的看到第一和第三个连接对象使用的是同一个连接。第二个连接对象使用得是新的连接。

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

添加连接

当创建一个池后,将创建多个连接对象并将其添加到该池中,以满足最小池大小的要求。连接根据需要添加到池中,但是不能超过指定的最大池大小(默认值为100)。连接在关闭或断开时释放回池中。在请求 SqlConnection 对象时,如果存在可用的连接,将从池中获取该对象。连接要可用,必须未使用,具有匹配的事务上下文或未与任何事务上下文关联,并且具有与服务器的有效链接。

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

池碎片

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

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

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

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

这也会对应用程序设计产生副作用。可通过一种相对简单的方法来避免此副作用,而不会影响连接到 SQL Server 时的安全性。连接到服务器上的相同数据库而不是为每个用户或组连接到单独的数据库,然后执行 T-SQL USE 语句来切换所需数据库。

【重读MSDN之ADO.NET】ADO.NET连接的更多相关文章

  1. ADO.NET基础巩固-----连接类和非连接类

          最近的一段时间自己的状态还是不错的,早上,跑步,上自习看书,下午宿舍里面编程实战,晚上要么练习代码,要么去打球(在不打就没机会了),生活还是挺丰富的. 关于C#的基础回顾就先到前面哪里,这 ...

  2. 第19课-数据库开发及ado.net ADO.NET--SQLDataReader使用.SqlProFiler演示.ADoNET连接池,参数化查询.SQLHelper .通过App.Config文件获得连接字符串

    第19课-数据库开发及ado.net ADO.NET--SQLDataReader使用.SqlProFiler演示.ADoNET连接池,参数化查询.SQLHelper .通过App.Config文件获 ...

  3. ADO与ADO.NET的区别与介绍

    1. ADO与ADO.NET简介ADO与ADO.NET既有相似也有区别,他们都能够编写对数据库服务器中的数据进行访问和操作的应用程序,并且易于使用.高速度.低内存支出和占用磁盘空间较少,支持用于建立基 ...

  4. ADO和ADO.NET的区别

    1. ADO与ADO.NET简介 ADO与ADO.NET既有相似也有区别,他们都能够编写对数据库服务器中的数据进行访问和操作的应用程序,并且易于使用.高速度.低内存支出和占用磁盘空间较少,支持用于建立 ...

  5. ADO和ADO.NET有什么不同?

    1.一些ADO中常见的类型比如RecordSet在ADO.NET中已经没有了,而且在ADO.NET中也新增了许多在传统ADO中找不到的直接对应的新类型(如数据适配器): 2.传统的ADO主要针对紧密连 ...

  6. [转帖]ODBC、OLEDB、ADO、ADO.NET

    一文详解ODBC.OLEDB.ADO.ADO.NET之间的关系 2019年01月16日 21:28:38 LoveMIss-Y 阅读数:66更多 所属专栏: 白话C#高级编程   版权声明:本文为博主 ...

  7. asp、asp.net、ado、ado.net各自区别和联系?

    asp.net与ado.net 的区别? asp.net是微软公司的.Net技术框架下的B/S(网页方向)框架技术.ado.net则是由asp.net编程语言编写的数据访问层的总括..说白了就是:as ...

  8. ADO.NET (二)—— ADO和ADO .NET对照

     ADO.NET (二)-- ADO和ADO .NET对照       我们知道ADO.NET的两大核心组件各自是Data Provider和DataSet.假设说 DataSet是ADO.NET的心 ...

  9. ADO与ADO.Net

    在介绍ADO.Net之前先让我们回想一下在红皮书中学习的ADO的内容. ADO(ActiveX Data Objects).我们称它为一种用于数据訪问的对象模型,<VB.Net>视频中称它 ...

随机推荐

  1. 流程控制之--if。

    假如把写程序比做走路,那我们到现在为止,一直走的都是直路,还没遇到过分叉口,想象现实中,你遇到了分叉口,然后你决定往哪拐必然是有所动机的.你要判断那条岔路是你真正要走的路,如果我们想让程序也能处理这样 ...

  2. Leecode刷题之旅-C语言/python-203移除链表元素

    /* * @lc app=leetcode.cn id=203 lang=c * * [203] 移除链表元素 * * https://leetcode-cn.com/problems/remove- ...

  3. 成都Uber优步司机奖励政策(3月20日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  4. 成都Uber优步司机奖励政策(2月26日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  5. 武汉Uber优步司机奖励政策(8月31日~9月6日)

    ·奖励前提 *必须满足当周平均评分4.7星及以上,且当周接单率70%及以上,当周在线5小时且完成5单,才有资格获得奖励 * 各组别必须满足当周要求的成单率才有资格获得奖励,成单率由当周 滴滴快车单单2 ...

  6. 16 pep8 编码规范

    pep8 编码规范 Python Enhancement Proposals :python改进方案 https://www.python.org/dev/peps/ 1. 每级缩进用4个空格. 括号 ...

  7. P1011 车站

    P1011 车站 题目描述 火车从始发站(称为第1站)开出,在始发站上车的人数为a,然后到达第2站,在第2站有人上.下车,但上.下车的人数相同,因此在第2站开出时(即在到达第3站之前)车上的人数保持为 ...

  8. LeetCode:36. Valid Sudoku(Medium)

    1. 原题链接 https://leetcode.com/problems/valid-sudoku/description/ 2. 题目要求 给定一个 9✖️9 的数独,判断该数独是否合法 数独用字 ...

  9. springboot之websocket

    一.WebSocket协议是基于TCP的一种新的网络协议.它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端. 二.长久以来, 创建实现客户端和用户端之间双工 ...

  10. 「国庆训练」ArcSoft's Office Rearrangement(HDU-5933)

    题目与分析 题解见https://blog.csdn.net/cmershen/article/details/53200922. 训练赛场上我们写出来了--在4小时50分钟的时候...激情补题啊.. ...