一. 如何处理数据库连接

1. 数据库连接可以分为“物理连接”和“逻辑连接”(默认使用连接池的情况下Pooling=true):

物理连接:创建数据库连接时,默认会有一定数量的物理连接(默认Min Pool Size = 0 表示建立1个物理连接,可以设置最多连接数,默认Max Pool Size = 100)

逻辑连接:基于物理连接上面会有若干逻辑连接(“连接池”),每次调用connection.close()时只是断开一个逻辑连接,将物理连接放回连接池。

数据库连接 (SqlConnection),由于它自动在底层隐藏着“连接池”机制的实现,那么如果程序不及时调用 Close(),而是等着 GC 那种延迟清理垃圾的机制,

那么就会造成“连接池满”的异常。所以在数据库操作后应及时断开连接(Close)。

2.常见的数据库连接处理方式:

第一种,using的使用。创建SqlConnection对象后,用完即释放(Dispose),dispose会先调用close

 using (SqlConnection connection = new SqlConnection(connectionString)){connection.open();//Do work}

第二种,try finally的使用。即在try步骤上Open,在finally步骤中Close

 SqlConnection conn = new SqlConnection(connectionString);try{conn.Open();// Do Work
 }catch (Exception e){// Handle and log error
 }finally{if(null!=conn)conn.Close();}

第三种,数据库类实现IDisposable接口中的Dispose方法一般情况下Dispose方法是用于垃圾回收器(GC)中的Finalize方法调用的,用来释放不再使用的对象资源,所以通常尽量不要去调用Dispose方法。垃圾回收器只会释放托管资源,而对于非托管资源(例如数据库连接的创建Open)则需要手动去关闭(释放)。如果手动释放了托管资源,则必须告诉GC已经手动释放了,GC不用再去做释放处理,否则会出错!Dispose方法包含无参和有参(disposing)

对于托管对象重写Dispose方法一般如下:
  public void Dispose(){this.Dispose(true);GC.SuppressFinalize(this);}

  bool disposed = false;

  private void Dispose(bool disposing)  {      if(disposed)      {          return;      }      if(disposing)      {          //释放托管资源       }      //释放非托管资源(如果有的话)

      this.disposed = true;

  }

  //如果有非托管资源,防止未释放,可以自定义析构函数  ~Class()  {      Dispose(false);  }

而一般情况下尽量不重写托管资源的Dispose方法,除非托管资源中包含非托管资源(数据库操作类中的连接资源),则Dispose方法中只关闭非托管资源,
而且并没有告诉GC该对象资源已经释放(没有调用GC.SuppressFinalize(this)方法),这样GC还是会定期回收对应的资源:
   class DBHandler:IDisposable{string connStr = "@...";SqlConnection conn = new SqlConnection(connStr);public DBHandler(){conn.Open();}

       public void HandlerAction()       {       }public void Dispose(){conn.Close();}}

   //其他地方调用   using(DBHandler Instance = new DBHandler())   {      Instance.HandlerAction();   }

二. 数据库操作类及方法 参照[c#操作数据库http://www.cnblogs.com/rainman/archive/2012/03/13/2393975.html]

1、概述

ado.net提供了丰富的数据库操作,这些操作可以分为三个步骤:

  • 第一,使用SqlConnection对象连接数据库;
  • 第二,建立SqlCommand对象,负责SQL语句的执行和存储过程的调用;
  • 第三,对SQL或存储过程执行后返回的“结果”进行操作。

对返回“结果”的操作可以分为两类:

  • 一是用SqlDataReader直接一行一行的读取数据集;
  • 二是DataSet联合SqlDataAdapter来操作数据库。

两者比较:

  • SqlDataReader时刻与远程数据库服务器保持连接,将远程的数据通过“流”的形式单向传输给客户端,它是“只读”的。由于是直接访问数据库,所以效率较高,但使用起来不方便。
  • DataSet一次性从数据源获取数据到本地,并在本地建立一个微型数据库(包含表、行、列、规则、表之间的关系等),期间可以断开与服务器的连接,使用SqlDataAdapter对象操作“本地微型数据库”,结束后通过SqlDataAdapter一次性更新到远程数据库服务器。这种方式使用起来更方,便简单。但性能较第一种稍微差一点。(在一般的情况下两者的性能可以忽略不计。)

一张十分出名的ADO.NET结构图:

2、连接字符串的写法

string connectString = "Data Source=.;Initial Catalog=Student;Integrated Security=True";

3、SqlConnection对象

命名空间:System.Data.SqlClient.SqlConnection;

返回数据库连接对象,参数字符串。实例化“连接对象”,并打开连接

SqlConnection sqlCnt = new SqlConnection(connectString);
sqlCnt.Open();

使用完成后,需要关闭“连接对象”

sqlCnt.Close();

4、SqlCommand对象

命名空间:System.Data.SqlClient.SqlCommand;

SqlCommand对象用于执行数据库操作,操作方式有三种:

  • SQL语句:command.CommandType = CommandType.Text;
  • 存储过程:command.CommandType = CommandType.StoredProcedure;
  • 整张表:command.CommandType = CommandType.TableDirect;

实例化一个SqlCommand对象

SqlCommand command = new SqlCommand();
command.Connection = sqlCnt;            // 绑定SqlConnection对象

或直接从SqlConnection创建

SqlCommand command = sqlCnt.CreateCommand();

常用方法:

  • command.ExecuteNonQuery(): 返回受影响函数,如增、删、改操作;
  • command.ExecuteScalar():执行查询,返回首行首列的结果(object类型);
  • command.ExecuteReader():返回一个数据流(SqlDataReader对象)。

常用操作

① 执行SQL
SqlCommand cmd = conn.CreateCommand();              //创建SqlCommand对象
cmd.CommandType = CommandType.Text;
cmd.CommandText = "select * from products = @ID";   //sql语句
cmd.Parameters.Add("@ID", SqlDbType.Int);
cmd.Parameters["@ID"].Value = 1;                    //给参数sql语句的参数赋值
② 调用存储过程
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "存储过程名";
③ 整张表
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = System.Data.CommandType.TableDirect;
cmd.CommandText = "表名"

5、SqlDataReader对象

命名空间:System.Data.SqlClient.SqlDataReader;

SqlDataReader对象提供只读单向数据的功能,单向:只能依次读取下一条数据;只读:DataReader中的数据是只读的,不能修改;相对地DataSet中的数据可以任意读取和修改.

它有一个很重要的方法,是Read(),返回值是个布尔值,作用是前进到下一条数据,一条条的返回数据,当布尔值为真时执行,为假时跳出。如SqlCommand command = new SqlCommand();

command.Connection = sqlCnt;
command.CommandType = CommandType.Text;
command.CommandText = "Select * from Users";
SqlDataReader reader = command.ExecuteReader()     //执行SQL,返回一个“流”if(reader.HasRows){while (reader.Read()){        if(reader["username"] != DBNull.Value) //非空        {             // string username = reader.GetString(0);Console.Write(reader["username"]); // 打印出每个用户的用户名        }}}

6、DataSet对象

6.1 SqlDataAdapter;

命名空间:System.Data.SqlClient.SqlDataAdapter;

SqlDataAdapter是SqlCommand和DataSet之间的桥梁,实例化SqlDataAdapter对象:

SqlConnection sqlCnt = new SqlConnection(connectString);
sqlCnt.Open();// 创建SqlCommand
SqlCommand mySqlCommand = new SqlCommand();
mySqlCommand.CommandType = CommandType.Text;
mySqlCommand.CommandText = "select * from product";
mySqlCommand.Connection = sqlCnt;// 创建SqlDataAdapter
SqlDataAdapter myDataAdapter = new SqlDataAdapter();
myDataAdapter.SelectCommand = mySqlCommand;    // 为SqlDataAdapter对象绑定所要执行的SqlCommand对象

上述SQL可以简化为

SqlConnection sqlCnt = new SqlConnection(connectString);
sqlCnt.Open();
// 隐藏了SqlCommand对象的定义,同时隐藏了SqlCommand对象与SqlDataAdapter对象的绑定
SqlDataAdapter myDataAdapter = new SqlDataAdapter("select * from product", sqlCnt);
属性和方法
  • myDataAdapter.SelectCommand属性:SqlCommand变量,封装Select语句;
  • myDataAdapter.InsertCommand属性:SqlCommand变量,封装Insert语句;
  • myDataAdapter.UpdateCommand属性:SqlCommand变量,封装Update语句;
  • myDataAdapter.DeleteCommand属性:SqlCommand变量,封装Delete语句。
  • myDataAdapter.fill():将执行结果填充到Dataset中,会隐藏打开SqlConnection并执行SQL等操作。

6.2 SqlCommandBuilder;

命名空间:System.Data.SqlClient.SqlCommandBuilder。

对DataSet的操作(更改、增加、删除)仅是在本地修改,若要提交到“数据库”中则需要SqlCommandBuilder对象。用于在客户端编辑完数据后,整体一次更新数据。具体用法如下:

SqlCommandBuilder mySqlCommandBuilder = new SqlCommandBuilder(myDataAdapter);  // 为myDataAdapter赋予SqlCommandBuilder功能
myDataAdapter.Update(myDataSet, "表名");                   // 向数据库提交更改后的DataSet,第二个参数为DataSet中的存储表名,并非数据库中真实的表名(二者在多数情况下一致)。

6.3 DataSet

命名空间:System.Data.DataSet。

数据集,本地微型数据库,可以存储多张表。

使用DataSet第一步就是将SqlDataAdapter返回的数据集(表)填充到Dataset对象中:

SqlDataAdapter myDataAdapter = new SqlDataAdapter("select * from product", sqlCnt);
DataSet myDataSet = new DataSet();     // 创建DataSet
myDataAdapter.Fill(myDataSet, "product"); // 将返回的数据集作为“表”填入DataSet中,表名可以与数据库真实的表名不同,并不影响后续的增、删、改等操作
① 访问DataSet中的数据
SqlDataAdapter myDataAdapter = new SqlDataAdapter("select * from product", sqlCnt);
DataSet myDataSet = new DataSet();
myDataAdapter.Fill(myDataSet, "product");DataTable myTable = myDataSet.Tables["product"];
foreach (DataRow myRow in myTable.Rows) {foreach (DataColumn myColumn in myTable.Columns) {Console.WriteLine(myRow[myColumn]);  //遍历表中的每个单元格}
}
② 修改DataSet中的数据
SqlDataAdapter myDataAdapter = new SqlDataAdapter("select * from product", sqlCnt);
DataSet myDataSet = new DataSet();
myDataAdapter.Fill(myDataSet, "product");// 修改DataSet
DataTable myTable = myDataSet.Tables["product"];
foreach (DataRow myRow in myTable.Rows) {myRow["name"] = myRow["name"] + "商品";
}// 将DataSet的修改提交至“数据库”
SqlCommandBuilder mySqlCommandBuilder = new SqlCommandBuilder(myDataAdapter);
myDataAdapter.Update(myDataSet, "product");

注意:在修改、删除等操作中表product必须定义主键,select的字段中也必须包含主键,否则会提示“对于不返回任何键列信息的 SelectCommand,不支持 UpdateCommand 的动态 SQL 生成。”错误

③ 增加一行
SqlDataAdapter myDataAdapter = new SqlDataAdapter("select * from product", sqlCnt);
DataSet myDataSet = new DataSet();
myDataAdapter.Fill(myDataSet, "product");
DataTable myTable = myDataSet.Tables["product"];// 添加一行
DataRow myRow = myTable.NewRow();
myRow["name"] = "捷安特";
myRow["price"] = 13.2;
//myRow["id"] = 100; id若为“自动增长”,此处可以不设置,即便设置也无效
myTable.Rows.Add(myRow);// 将DataSet的修改提交至“数据库”
SqlCommandBuilder mySqlCommandBuilder = new SqlCommandBuilder(myDataAdapter);
myDataAdapter.Update(myDataSet, "product");
④ 删除一行
SqlDataAdapter myDataAdapter = new SqlDataAdapter("select * from product", sqlCnt);
DataSet myDataSet = new DataSet();
myDataAdapter.Fill(myDataSet, "product");// 删除第一行
DataTable myTable = myDataSet.Tables["product"];
myTable.Rows[0].Delete();SqlCommandBuilder mySqlCommandBuilder = new SqlCommandBuilder(myDataAdapter);
myDataAdapter.Update(myDataSet, "product");
属性
  • Tables:获取包含在DataSet中的表的集合。
  • Relations:获取用于将表链接起来并允许从父表浏览到子表的关系的集合。
  • HasEroors:表明是否已经初始化DataSet对象的值。
方法
  • Clear清除DataSet对象中所有表的所有数据。
  • Clone复制DataSet对象的结构到另外一个DataSet对象中,复制内容包括所有的结构、关系和约束,但不包含任何数据。
  • Copy复制DataSet对象的数据和结构到另外一个DataSet对象中。两个DataSet对象完全一样。
  • CreateDataReader为每个DataTable对象返回带有一个结果集的DataTableReader,顺序与Tables集合中表的显示顺序相同。
  • Dispose释放DataSet对象占用的资源。
  • Reset将DataSet对象初始化。

7、释放资源

资源使用完毕后应及时关闭连接和释放,具体方法如下:

myDataSet.Dispose();        // 释放DataSet对象
myDataAdapter.Dispose();    // 释放SqlDataAdapter对象
myDataReader.Dispose();     // 释放SqlDataReader对象
sqlCnt.Close();             // 关闭数据库连接
sqlCnt.Dispose();           // 释放数据库连接对象默认释放连接时会先释放存在绑定之的Command,DataReader等对象)

ref : http://www.cnblogs.com/rainman/archive/2012/03/13/2393975.html
ref : http://www.cnblogs.com/eaglet/archive/2011/10/31/2230197.html
 

转载于:https://www.cnblogs.com/leenice/p/5590027.html

c# 数据库操作学习相关推荐

  1. C# SQLite 数据库操作语句与文件视图管理器

    //sqlite数据库视图管理器 SQLiteSpy是一款专业的SQLite数据库管理,主要用于读取sqlite数据库,建立新的SQL查询,视图,复制和删除表.编辑单元格,以及查看索引,触发器和排序规 ...

  2. python连接access数据库查询并打印出来_python 查询 access数据库操作

    日志服务使用Python SDK快速入门指南 为快速开始使用日志服务Python SDK,请按照如下步骤进行: 创建阿里云账号 为了访问阿里云日志服务,你需要有一个阿里云账号.如果没有,可首先如下创建 ...

  3. DSP学习 -- C语言实现MySQL数据库操作

    如需转载请注明出处 https://juyou.blog.csdn.net/article/details/109259673 要实现在VS上使用C语言操作MySQL数据库.接下来看一下该怎么操作. ...

  4. MySql学习笔记(2)--数据库操作及数据管理

    2.数据库操作 操作数据库>操作数据库中的表>操作数据库中表的数据 mysql关键字区分大小写 2.1操作数据库 1.创建数据库 create database if not exists ...

  5. 数据库操作的学习(一)

    数据库操作的学习(以SQLServer为例) 前提准备 使用JDBC操作数据库的基本步骤 加载JDBC驱动包和连接数据库 数据库查询 增删改 批处理 动态查询 调用存储过程 关闭驱动类 前提准备 在S ...

  6. Flas-SQLAchemy数据库操作使用学习笔记

    Flas-SQLAchemy数据库操作使用学习笔记 Flask-SQLALchemy 是一个给你的应用添加 SQLALchemy 支持的 Flask 扩展.SQLALchemy 是Python语言的S ...

  7. python学习第6天---django框架---模型类及数据库操作

    python学习第6天---django框架---模型类及数据库操作 目录 文章目录 1.字段与选项 2.查询函数 3.查询集 4.模型类之间的关系 4.1.对应关系 4.2.关联查询 5.模型管理器 ...

  8. 技能学习:学习使用php(tp6框架) + vue.js,开发前端全栈网站-3.路由、模型与数据库操作

    技能学习:学习使用php(tp6框架) + vue.js,开发前端全栈网站-3.路由.模型与数据库操作 技能学习:学习使用php(tp6框架) + vue.js,开发前端全栈网站-1.工具和本地环境 ...

  9. 【gin学习笔记】07初识GROM使用GORM进行数据库操作

    本文学习视频https://www.bilibili.com/video/BV1Bz411v78U/?spm_id_from=333.788 gorm中文官方文档 https://jasperxu.c ...

最新文章

  1. 你想要的生信知识全在这——生信宝典目录 (181202)
  2. 带你用深度学习虚拟机进行文本迁移学习(附代码)
  3. js轮播图代码_javascript基础(一)——轮播图
  4. 蓝湖怎么切图标注_【蓝湖指北】一张图教你如何选择标注尺寸
  5. torch.cat同时连接多个tensor
  6. C语言 | 给偶数寻素数
  7. 深入理解linux根目录结构
  8. SAP Marketing 和SAP marketing Cloud的区别
  9. mongodb 监控权限_MongoDB - 监控
  10. JSP的9个内置对象-application
  11. mac忘记MySQL初始密码
  12. 在 Chrome 控制台可以玩的两个骚操作,你知道吗?
  13. mysql导出kml_谷歌地图如何导出kml文件 导出kml文件教程
  14. opencv 实现图像时钟
  15. server 2008 R2+IIS7.5安装cacti实验
  16. Object对象的内存布局学习总结
  17. C# 类中的静态代码块
  18. Android学习资料整理
  19. win10磁盘使用率100%的解决方法
  20. 基于Python实现的手写数字识别系统

热门文章

  1. 一张图讲清如何正确应用可视化图表,学会后再也不会用错图表
  2. 使用ByteArray及AMF来提高Data Object的操作效率
  3. matlab编写信号采集程序,MATLAB语音信号采集课程设计
  4. php多进程采集百度,php实现多进程下载百度网盘文件
  5. android应用程序列表,List列表应用程序-小知识 #103
  6. centos php 5.2,CentOS服务器单独升级 php5.1 到 5.2版本
  7. java泛型实验报告,java实验报告异常集合类和泛型
  8. mysql cpu高 重启无效_解决mysqlcpu高的问题
  9. 操作手册模板_挂蓝悬臂浇筑箱梁施工技术操作手册
  10. python字符串匹配算法_Python实现字符串匹配算法