【重读MSDN之ADO.NET】ADO.NET连接
连接到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连接的更多相关文章
- ADO.NET基础巩固-----连接类和非连接类
最近的一段时间自己的状态还是不错的,早上,跑步,上自习看书,下午宿舍里面编程实战,晚上要么练习代码,要么去打球(在不打就没机会了),生活还是挺丰富的. 关于C#的基础回顾就先到前面哪里,这 ...
- 第19课-数据库开发及ado.net ADO.NET--SQLDataReader使用.SqlProFiler演示.ADoNET连接池,参数化查询.SQLHelper .通过App.Config文件获得连接字符串
第19课-数据库开发及ado.net ADO.NET--SQLDataReader使用.SqlProFiler演示.ADoNET连接池,参数化查询.SQLHelper .通过App.Config文件获 ...
- ADO与ADO.NET的区别与介绍
1. ADO与ADO.NET简介ADO与ADO.NET既有相似也有区别,他们都能够编写对数据库服务器中的数据进行访问和操作的应用程序,并且易于使用.高速度.低内存支出和占用磁盘空间较少,支持用于建立基 ...
- ADO和ADO.NET的区别
1. ADO与ADO.NET简介 ADO与ADO.NET既有相似也有区别,他们都能够编写对数据库服务器中的数据进行访问和操作的应用程序,并且易于使用.高速度.低内存支出和占用磁盘空间较少,支持用于建立 ...
- ADO和ADO.NET有什么不同?
1.一些ADO中常见的类型比如RecordSet在ADO.NET中已经没有了,而且在ADO.NET中也新增了许多在传统ADO中找不到的直接对应的新类型(如数据适配器): 2.传统的ADO主要针对紧密连 ...
- [转帖]ODBC、OLEDB、ADO、ADO.NET
一文详解ODBC.OLEDB.ADO.ADO.NET之间的关系 2019年01月16日 21:28:38 LoveMIss-Y 阅读数:66更多 所属专栏: 白话C#高级编程 版权声明:本文为博主 ...
- asp、asp.net、ado、ado.net各自区别和联系?
asp.net与ado.net 的区别? asp.net是微软公司的.Net技术框架下的B/S(网页方向)框架技术.ado.net则是由asp.net编程语言编写的数据访问层的总括..说白了就是:as ...
- ADO.NET (二)—— ADO和ADO .NET对照
ADO.NET (二)-- ADO和ADO .NET对照 我们知道ADO.NET的两大核心组件各自是Data Provider和DataSet.假设说 DataSet是ADO.NET的心 ...
- ADO与ADO.Net
在介绍ADO.Net之前先让我们回想一下在红皮书中学习的ADO的内容. ADO(ActiveX Data Objects).我们称它为一种用于数据訪问的对象模型,<VB.Net>视频中称它 ...
随机推荐
- Hadoop端口
本文转自:<Hadoop默认端口应用一览> Hadoop集群的各部分一般都会使用到多个端口,有些是daemon之间进行交互之用,有些是用于RPC访问以及HTTP访问.而随着Hadoop周边 ...
- spring作用
在SSH框假中spring充当了管理容器的角色.我们都知道hibernate用来做持久层,因为它将JDBC做了一个良好的封装,程序员在与数据库进行交互时可以不用书写大量的SQL语句.Struts是用来 ...
- 洛谷P4136 谁能赢呢?
题目描述 小明和小红经常玩一个博弈游戏.给定一个n×n的棋盘,一个石头被放在棋盘的左上角.他们轮流移动石头.每一回合,选手只能把石头向上,下,左,右四个方向移动一格,并且要求移动到的格子之前不能被访问 ...
- Qt的4个图像类QImage/QPixmap/QBitmap/QPicture 转
Qt的4个图像类QImage/QPixmap/QBitmap/QPicture 转 (一)QPixmap和QImage的区别 http://www.thisisqt.com/forum/viewthr ...
- P1294 高手去散步
P1294 高手去散步 题目背景 高手最近谈恋爱了.不过是单相思.“即使是单相思,也是完整的爱情”,高手从未放弃对它的追求.今天,这个阳光明媚的早晨,太阳从西边缓缓升起.于是它找到高手,希望在晨读开始 ...
- LeetCode: 56. Merge Intervals(Medium)
1. 原题链接 https://leetcode.com/problems/merge-intervals/description/ 2. 题目要求 给定一个Interval对象集合,然后对重叠的区域 ...
- maven的两种打包方式
1.maven目前在web上面的使用方式很普遍,而打包的方式也存在很多方式 2.因为涉及一个项目调用另外一个项目的包,并将另外一个项目打成jar的形式便于管理 3.maven打包第一种方式: 将项目检 ...
- lunix安装
https://www.cnblogs.com/wcwen1990/p/7630545.html
- 「日常温习」Hungary算法解决二分图相关问题
前言 二分图的重点在于建模.以下的题目大家可以清晰的看出来这一点.代码相似度很高,但是思路基本上是各不相同. 题目 HDU 1179 Ollivanders: Makers of Fine Wands ...
- Linux命令应用大词典-第16章 归档和压缩
16.1 tar:进行归档和压缩 16.2 gzip:压缩或解压缩gzip文件 16.3 gunzip:解压缩gzip文件 16.4 zcmp:比较gzip压缩文件 16.5 zdiff:比较gzip ...