3.1.Ado.Net访问数据库的基本过程
1) 创建连接对象 ------->2) 创建命令对象-------> 3)打开连接 -------> 4) 执行命令-----> 5)关闭连接
3.2 SqlConnection对象介绍
SqlConnection:继承于 DbConnection 抽象基类,不能被实例化。提供与SqlServer数据库的连接。
常用属性:
ConnectionString 连接字符串 --- 钥匙
State 连接状态
DataBase 连接的数据库名
DataSource 数据源(SQLServer实例名) 本地:(local)或 . 远程: ip,端口号
State状态值 : Closed 已关闭
Open 打开
Connecting 正在连接
Executing 正在执行命令
Fetching 正在检索数据
Broken 连接中断
常用方法
Open()—— 打开连接 OpenAsync() Open的异步方法
Close() ——关闭连接
Dispose() 释放连接
BeginTransaction() 开始数据库事务
**CreateCommand() ** 创建并返回一个与 SqlConnection 关联的SqlCommand 对象
3.3 连接字符串
连接字符串:一个字符串,一组被格式化的键值对,指明:数据源在哪里,数据库名是什么,提供什么样访问信任级别,其他相关信息(最大、小连接数,超时设置等)。
格式:由一组元素组成,每一个元素---键值对,各个元素之间用“ ;” 隔开。
如:
string connStr="key1=value; key2=value2;........"
3.3.1SQLServer连接字符串
两种验证:
//1) **Sql server 身份验证**
Data Source=数据源; Initial Catalog=数据库名; User Id=账号; Password=密码
//2) **Windows身份验证**
Data Source=数据源;Initial Catalog=数据库名; Integrated Security=True/SSPI (或 Trusted_Connection=True)
以上两种验证的简单写法:
//Server=.;DataBase=数据库名;UId=账号;Pwd=密码
//Server=.;DataBase=数据库名;Integrated Security=true
//如:
string connStr="Server=.;DataBase=TestDB;UId=sa;Pwd=1234";
string connStr="Server=.;DataBase=TestDB;Integrated Security=true";
3.3.2 构建连接字符串
连接字符串可以手写,也可以通过SqlConnectionStringBuilder类来构建。
1) 手写连接字符串
string connStr = "server=. ; database=HMDBase;uid=sa;pwd=1234";
2)使用SqlConnectionStringBuilder类来构建
SqlConnectionStringBuilder connStrBuilder = new SqlConnectionStringBuilder();
connStrBuilder.DataSource = ".";//设置数据源
connStrBuilder.InitialCatalog = "HMDBase";//数据库名
connStrBuilder.UserID = "lyc";//账号
connStrBuilder.Password = "123456";//密码
connStrBuilder.Pooling = false;//禁用连接池
string connStr = connStrBuilder.ConnectionString; //获取生成的连接字符串
3.3.3 配置连接字符串
程序代码中写连接字符串,如果要修改,需要再次重新编译——灵活性很差
如何解决?
——存储在配置文件
写在app.config或web.config配置文件中的<connectionStrings>或<appSettings>节点里
但最好写在 <connectionStrings>节点中,这个节点专门用于配置数据库连接字符串的
//写在connectionStrings节点中----最好写在该节点中
<connectionStrings><add name="connStr" connectionString="Server=.;DataBase=HotelMemberDBase;UId=lyc;Pwd=123456" providerName="System.Data.SqlClient"/>
</connectionStrings>//写在appSettings节点中 ----- 此节点一般用于配置应用程序相关信息的
<appSettings><add key="connStr" value="Server=.;DataBase=HotelMemberDBase;UId=lyc;Pwd=123456"/>
</appSettings>
新问题:怎么从从配置文件中取连接字符串???
步骤1:引用 System.Configuration 程序集
步骤2:在后台代码类中,能过以下代码读取:
string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString;//读取连接字符串
如果配置在中:
string connStr = ConfigurationManager.AppSettings["connStr"].ToString();
3.4 SqlConnection对象创建与使用
1.创建连接
实例化:new SqlConnection(ConnString)--推荐
SqlConnection conn=new SqlConnection(connStr);
2.使用 (一般时创建好命令后,需要执行时才打开连接)
需要使用连接时,用Open()方法打开连接
执行数据库命令(insert update delete select)
//创建执行命令对象
//需要执行命令时
conn.Open();
//执行命令
//关闭连接
3.释放
Close() --关闭连接 关闭后可再打开
Dispose() --释放连接 释放后,ConnString为空了,得重新设置
using(){} --使用using释放的对象,必须实现IDisposable接口
3.5 连接池
3.5.1 连接池介绍
1.为什么要使用连接池?
建立连接,是非常耗时耗力一件事。
要经历几个阶段:建立物理通道、与服务器初次的握手、分析连接字符串、身份验证,运行检查等。。
每次要建立连接都需要经历这些过程——相当的痛苦,怎样重复利用已有的连接? ---- 连接池
2.连接池是什么?
容器:存放了一定数量的与数据库服务器的物理连接。
需要时,从容器里取出一条空闲的连接,而不是创建一条新的连接。
作用: 减少了连接数据库的开销,从而提高了应用程序的性能。
3.5.2 连接池分类
类别区分,同一时刻同一应用程序域可以有多个不同类型的连接池。
什么来标识区分??
----进程、应用程序域、连接字符串、windows标识 共同组成的签名来标识区分。
对同一程序域来说,由 连接字符串 来区分。(比较连接字符串是否完全一样)
打开一条连接,如果 这条连接的类型签名与现有的连接不匹配,就会创建一个新的连接池,
反之则不会创建,相同的连接字符串共用同一个连接池。
3.5.3 分配、移除、释放连接
分配连接
根据连接请求的类型,找到与它相匹配的连接池,尽力的分配一条空闲的连接。
有空闲的连接,返回这条连接
已用完,创建一个新连接添加连接池中
已达到了最大连接数,等待,直到有空闲的连接可用。
移除无效连接
不能正确的连接到数据库服务器的连接 ——无效连接,
我们应当移除无效连接,以免浪费连接池空间
连接池管理器会处理无效连接的移除问题。
回收连接
使用完的连接?—— 应当即时关闭或释放,
调用连接对象的Close()、 Dispose() ——连接回到连接池。
3.5.4 连接池的应用
Ado.Net 默认是 启用连接池的。
连接字符串是可以控制连接池的行为的。
三个属性:
Max Pool Size :最大连接数 默认:100
Min Pool Size :最小连接数 默认:0
Pooling: 是否启用连接池 默认:true
测试1:连接池的存在??
private void Test1()
{string connStr1 = "Server=.;DataBase=HotelMemberDBase;UId=lyc;Pwd=123456;Max Pool Size=5";for (int i = 0; i < 10; i++){SqlConnection conn = new SqlConnection(connStr1);conn.Open();Console.WriteLine($"连接conn{i} 已打开!");}
}
测试2:是否启用连接池的耗时比较??
private void Test2()
{//启用连接池string connStr1 = "server =.; database = HotelMemberDBase;uid = lyc;pwd = 123456;Pooling=true";Stopwatch sw = new Stopwatch();//测量执行时间sw.Start();for (int i = 0; i < 100; i++){SqlConnection conn = new SqlConnection(connStr1);conn.Open();Console.WriteLine($"连接conn{i} 已打开!");conn.Close();}sw.Stop();//不启用连接池Stopwatch sw1 = new Stopwatch();sw1.Start();string connStr2 = "server =.; database =HotelMemberDBase;uid = lyc;pwd = 123456;Pooling=false";for (int i = 0; i < 100; i++){SqlConnection conn = new SqlConnection(connStr2);conn.Open();Console.WriteLine($"连接conn{i} 已打开!");conn.Close();}sw1.Stop();Console.WriteLine("有连接池耗时:" + sw.ElapsedMilliseconds);Console.WriteLine("无连接池耗时:" + sw1.ElapsedMilliseconds);
}
测试3:连接池类别区分测试??
private void Test3(){//connStr1 connStr2 connStr3都是连接会员数据库,2、3完全一样,1中有空格string connStr1 = "server =.; database = HotelMemberDBase; uid = sa; pwd = 123456;Pooling=true;Max Pool Size=5";string connStr2 = "server =.; database = HotelMemberDBase;uid = sa; pwd = 123456;Pooling=true;Max Pool Size=5";string connStr3 = "server =.; database = HotelMemberDBase;uid = sa; pwd = 123456;Pooling=true;Max Pool Size=5";//总共建10个连接,看结果:2\3共用同一连接池,1单独一连接池for (int i = 0; i < 10; i++){SqlConnection conn2 = new SqlConnection(connStr2);conn2.Open();Console.WriteLine($"连接conn2{i} 已打开!");SqlConnection conn3 = new SqlConnection(connStr3);conn3.Open();Console.WriteLine($"连接conn3{i} 已打开!");SqlConnection conn1 = new SqlConnection(connStr1);conn1.Open();Console.WriteLine($"连接conn1{i} 已打开!");}}