C# 数据库操作
1,ADO.NET 类和对象概述
类分为.NET 数据提供者对象和用户对象
提供者对象专用于每种类型数据源,专用于提供者的对象完成数据源中实际的读取和写入工作。
用户对象是将数据读入内存中后来访问和操纵数据的对戏那个。
提供者需要一个活动的连接,可以读取,写入,更新数据源中的数据。用户对象以非连接的方式使用,甚至在数据库关闭之后,也可以使用内存中的数据。
2,提供者对象
【1】连接对象:提供了数据源的基本连接,类似于ADO中的Connection字串的连接。
【2】命令对象:可以使用此对象给数据源发出命令,比如:“select * from customers”查询等,对于不同的提供者,该对象的名称而不同,SQL Server 的SqlCommand,用于ODBC的OdbcCommand,用于OLE DB 的OleDbCommand
【3】CommandBuilder对象
用于构建SQL命令,在基于单一表查询的对象中进行数据修改。对于不用的提供者名称有所不同,SqlCommandBuilder,OdbcCommandBuilder,OleDbCommandBuilder.
【4】DataReader 对象
这是一个快速和易用的对象,可以从数据源中读取仅能前向和只读的数据流,对于简单的读取数据来说,此对象的性能最好。对于不同的提供者,名称有所不同。分别:SqlDataReader,OdbcDataReader,OleDbDataReader
【5】DataAdapter对象
这是一个通用的类,可以执行针对数据源的各种操作,包括更新变动的数据,填充DataSet对象以及其他操作。对于不同的提供者名称有所不同。分别:SqlDataAdapter,OdbcDataAdapter,OleDbDataAdapter
3,用户对象
【1】DataSet对象
DataSet对象是用户对象中的首要对象,此时对象表示一组相关表,在应用程序中这些表作为一个单元来引用。例如:Customer,Orders和Products是一个DataSet中的表,他们表示每一位顾客和他们从公司中订购的产品,有了此对象,可以快捷的从每一个表中获取需要的数据,当与服务区断开时检查并修改数据,然后在另一个操作中使用这些修改的数据更新服务器。DataSet允许访问低级对象,这些对象代表单独的表和关系。这些对象是DataTable对象和DataRelation对象。
【2】DataTable对象
此对象代表DataSet中的一个表。例如:Customer,Orders或Products
DataTable对象允许访问其中的行和列:
DataColumn对象:代表表中的一列
DataRow对象:代表表中的一行
【3】DataRelation对象
此对象代表通过共享列而发生关系的两个表之间的关系,例如Order表中的CustomerID列标示发出订单的客户。于是,可以创建DataRelation对象,通过共享列CustomerID建立Customer和Order表之间的联系。
4,使用System.Data命名空间
在C#代码中使用ADO.NET的第一步是引用System.Data命名空间,其中包含所有的Ado.Net类,将下面using指令放在使用Ado.net程序的开端:
using System.Data;
接着需要为使用的特定数据源引用.NET数据提供者。
【1】SQL Server .NET 数据提供者
使用专用的内置.NET 数据提供者就可以获得最好的性能和对基础功能的最直接访问。
using System.Data.SqlClient;
【2】Oracle .NET 数据提供者
使用Oracle数据库,内置Oracle .NET驱动程序是最佳选择。项目文件上点击右键,选择添加引用,然后找到.net选项卡的System.Data.OracleClient,点击确认即可。(比上面麻烦一些)然后就可以用下面的语句。
using System.Data.OracleClient;
Oracle本身也提供了一个.NET数据提供者,引用为Oracle.DataAccess.Client,它必须从Oracle中单独下载。这个驱动可以更多的利用数据库产品的特定功能,但对于基本的使用来说,都可以。
【3】OLE DB.NET数据提供者
对于不是SQLServer或Oracle的数据源(例如Access),可以使用OLE DB.NET 数据提供者。
using System.Data.OleDb;
【4】ODBC.NET数据提供者
using System.Data.Odbc;
5,用DataReader读取数据
程序:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; //注意 using System.Data.OracleClient; //Oracle数据库 namespace ConsoleApplication4 { class Program { static void Main(string[] args) { //Data Source=orcl;User ID=shibei;Password=nsic;Unicode=True OracleConnection myConnection = new OracleConnection(@"Data Source=orcl;User ID=shibei;Password=nsic;Unicode=True");//创建连接对象 myConnection.Open(); //建立连接 OracleCommand myCommand = myConnection.CreateCommand(); //创建命令对象 myCommand.CommandText = "select * from N_AIT"; //提供SQL命令 OracleDataReader myReader = myCommand.ExecuteReader(); //执行命令返回结果指派给DataReader对象 while (myReader.Read()) //从读取器中获取结果 { Console.WriteLine("{0}\t{1}", myReader["ID"], myReader["NAME"]); } myReader.Close();//关闭DataReader myConnection.Close();//关闭数据库连接 } } }
运行结果:
注意:如果本例要使用OleDb进行连接的话,除了把using System.Data.OracleClient; 改成using System.Data.OleDb;把OracleConnection等改成OleDbConnection等。唯一的区别就是连接字符串,生成连接字符串的方法可以在。数据-显示数据源-添加新数据源。配置好之后就可以看到连接字符串了,一定要包含敏感字符啊,不然密码就没了,呵呵。
6,用DataSet读取数据
DataSet是Ado.Net中的核心对象,所有复杂级别的操作都使用它。DataSet包含一组DataTable对象,他们表示操作的数据库表。DataSet的常见操作使用DataAdapter对象Fill方法给他填充数据为什么Fill方法是DataAdapter对象的方法,而不是DataSet的方法呢,因为DataSet是内存中数据的一个抽象表示,而DataAdapter对象是把DataSet和具体的数据库联系起来的对象,Fill方法有很多重载版本,本例中使用两个参数的,第一个指定要填充的DataSet,第二个参数是DataSet中要包含所加载数据的DataTable名称。DataSet对象有一个Tables属性,他是DataSet中所有DataTable对象的集合。Tabels的类型是DataTableCollection,他有一个重载的索引符,于是可以用两种方式访问每个DataTable
【1】按表名访问:thisDataSet.Tables[“Customers”]
【2】按索引访问:thisDataSet.Tables[0]
每一个DataTable都有一个Rows属性,他是DataRow对象的集合。Rows的类型是DataRowCollection,是一个有序列表,按行号排序。例:myDataSet.Tables[“Customers”].Rows[n]表示在thisDataSet的DataTable对象Customers中指定行号n-1(索引是基于0的)。当然也可以使用其他索引语法来制定DataTable。我们希望DataRow也有一个DataColumnCollection类型的属性,但是事实并不是那么简单,因为要利用那个每一行各个列中的数据类型,是包含字符数据的列是一个字符串,包含整数的列是一个整数对象等等。DataRow有一个重载的索引,允许按列名和列号访问各个列。
thisDataSet.Table[“Customers”].Rows[n][“CompanyName”]
在thisDataSet的DataTable对象Customers中指定行号为n-1的CompanyName列,这里DataRow对象是thisDataSet.Tables[“Customers”].Rows[n],上述结构有点混乱,给出了其图形显示。
程序:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; //注意 using System.Data.OracleClient; //Oracle数据库 namespace ConsoleApplication4 { class Program { static void Main(string[] args) { //Data Source=orcl;User ID=shibei;Password=nsic;Unicode=True OracleConnection thisConnection = new OracleConnection(@"Data Source=orcl;User ID=shibei;Password=nsic;Unicode=True"); // thisConnection.Open();//此处可以不用打开 OracleDataAdapter thisAdapter = new OracleDataAdapter("select * from N_AIT", thisConnection); DataSet thisDataSet = new DataSet(); thisAdapter.Fill(thisDataSet, "MY_N_AIT");//MY_N_AIT不是表名而是DataTable对象的名称 foreach (DataRow theRow in thisDataSet.Tables["MY_N_AIT"].Rows)//注意与上面的MY_N_AIT要对上哦 { Console.WriteLine(theRow["ID"] + "\t" + theRow["NAME"]);//除了用名字也可以用索引号 } thisConnection.Close();//这个例子中没有明确打开连接,因为DataAdapter对象完成了这个工作, //数据授权对象会根据需要打开连接,在完成工作后关闭它。 //DataAdapter对象不改变连接的状态,如果DataAdapter对象开始其工作前连接时打开的, //在DataAdapter对象完成其工作后,连接仍是打开的。( 不懂既然DataAdapter来处理为什么不改变连接的状态) } } }
运行结果同上。
注意:DataReader工作时必须要维护数据库的连接,而且只能向前的方式读取数据,可以浏览记录或跳到某一记录上。而且只能读取记录。而用DataAdapter对象填充了DataSet,DataAdapter对象需要处理连接的打开和关闭。DataSet为数据的读写以及操作不同数据源中的数据提供了极大的灵活性。下面相继介绍。
7,更新数据库
本例中给出一个非常简单的示例,此示例仅使用了一个表,同时引入后面才会介绍的几个新对象。
在数据库上进行的操作(更新,插入,删除)可以用相同的模式完成。
代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; //注意 using System.Data.OracleClient; //Oracle数据库 namespace ConsoleApplication4 { class Program { static void Main(string[] args) { OracleConnection thisConnection = new OracleConnection(@"Data Source=orcl;User ID=shibei;Password=nsic;Unicode=True"); OracleDataAdapter thisAdapter = new OracleDataAdapter("select * from N_AIT", thisConnection); OracleCommandBuilder thisBuilder = new OracleCommandBuilder(thisAdapter);//CommandBuilder用来创建SQL指令,与Adapter相关联 DataSet thisDataSet = new DataSet(); thisAdapter.Fill(thisDataSet, "MY_N_AIT");//MY_N_AIT不是表名而是DataTable对象的名称 Console.WriteLine("Name before change:{0}", thisDataSet.Tables["MY_N_AIT"].Rows[4]["NAME"]); thisDataSet.Tables["MY_N_AIT"].Rows[4]["NAME"] = "被我改了";//数据被修改 thisAdapter.Update(thisDataSet, "MY_N_AIT");//SQL的指令时靠CommandBuilder来完成的,这要求建立Adapter的查询语句中的字段 //必须有主键,如果没有的话这样执行就抛出异常了。 thisConnection.Close();//这个例子中没有明确打开连接,因为DataAdapter对象完成了这个工作, //数据授权对象会根据需要打开连接,在完成工作后关闭它。 //DataAdapter对象不改变连接的状态,如果DataAdapter对象开始其工作前连接时打开的, //在DataAdapter对象完成其工作后,连接仍是打开的。( 不懂既然DataAdapter来处理为什么不改变连接的状态) } } }
运行结果:
实际数据库中数据将被改写:
注意:利用OracleCommandBuilder产生SQL语句,但是表中必须要有主键,否则会抛出异常。采用直接执行SQL命令可以解决。
8,直接执行SQL命令
程序:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; //注意 using System.Data.OracleClient; //Oracle数据库 namespace ConsoleApplication4 { class Program { static void Main(string[] args) { OracleConnection thisConnection = new OracleConnection(@"Data Source=orcl;User ID=system;Password=myoracle;Unicode=True"); thisConnection.Open();//此处可以不用打开 OracleCommand thisCommand = thisConnection.CreateCommand(); thisCommand.CommandText = "select count(*) from Histalamt"; Object countResult = thisCommand.ExecuteOracleScalar(); Console.WriteLine("Count = {0}", countResult); thisConnection.Close(); Console.ReadKey(); } } }
运行结果:
9,不检索数据
代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; //注意 using System.Data.OracleClient; //Oracle数据库 namespace ConsoleApplication4 { class Program { static void Main(string[] args) { OracleConnection thisConnection = new OracleConnection(@"Data Source=orcl;User ID=shibei;Password=nsic;Unicode=True"); thisConnection.Open();//此处可以不用打开 OracleCommand thisCommand = thisConnection.CreateCommand(); thisCommand.CommandText = "update N_AIT set NAME = '改你了,怎么地' where ID = 34251"; int rows = 0; try { rows = thisCommand.ExecuteNonQuery();//返回行数 //取出返回值 Console.WriteLine(Convert.ToString(rows)); } catch (Exception er) { string merr = "err:" + er.ToString(); Console.WriteLine(merr); } finally { thisConnection.Close(); thisConnection.Dispose();//释放所有资源 thisCommand.Parameters.Clear(); thisCommand.Dispose();//释放所有资源 } } } }
运行结果:
更改后的表:
注意:此方法对删除和插入同样有效哦
10,调用SQL存储过程
代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; //注意 using System.Data.OracleClient; //Oracle数据库 namespace ConsoleApplication4 { class Program { static void Main(string[] args) { OracleConnection thisConnection = new OracleConnection(@"Data Source=orcl;User ID=system;Password=myoracle;Unicode=True"); thisConnection.Open();//此处可以不用打开 OracleCommand thisCommand = thisConnection.CreateCommand(); thisCommand.CommandType = CommandType.StoredProcedure; thisCommand.CommandText = "or_test"; int rows = 0; string rtnStr; try { OracleParameter[] parm = new OracleParameter[2]; //in parm[0] = new OracleParameter("myid", OracleType.Number, 3); parm[1] = new OracleParameter("myname", OracleType.VarChar, 50); //指明参数是输入还是输出型 parm[0].Direction = ParameterDirection.Input; parm[1].Direction = ParameterDirection.Output; //给参数赋值 parm[0].Value = 350; //传递参数给Oracle命令 thisCommand.Parameters.Add(parm[0]); thisCommand.Parameters.Add(parm[1]); rows = thisCommand.ExecuteNonQuery();//返回行数 //取出返回值 rtnStr = Convert.ToString(parm[1].Value);//res Console.WriteLine(rtnStr); Console.WriteLine(Convert.ToString(rows)); } catch (Exception er) { string merr = "err:" + er.ToString(); Console.WriteLine(merr); } finally { thisConnection.Close(); thisConnection.Dispose();//释放所有资源 thisCommand.Parameters.Clear(); thisCommand.Dispose();//释放所有资源 } } } }
存储过程:
运行结果: