参考:
https://www.cnblogs.com/zyh000/p/10253796.html
概念
ADO.NET简单理解就是,微软定义了一堆关于操作数据源的接口和类,是C#语言访问数据源的一种方式,ADO.NET 类位于 System.Data.dll
常用对象
- Connection → 数据库连接器
- Command → 数据库命名对象
- DataReader →数据读取器
- DataAdapter →数据适配器,填充DataSet
Connection
Connection是数据库连接对象,Connection的功能是负责对数据源的连接。所有Connection对象的基类都是DbConnection类(IDbConnection接口),DbConnection 类位于 System.Data.Common.dll
不同的数据源对应不同的Connection 对象:SqlConnection(sqlserver)、OledbConnection(oledb)、MySqlConnection(mysql)、OracleConnection(oracle)
连接字符串
-
SQL链接字符串:“Data Source=.;Initial Catalog=ax_log;User Id=sa;Password=sa;”
-
MySql链接字符串:"server=.;database=ax_log;user id=sa;password=sa;Charset=utf8"
-
Access链接字符串:“Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:Database.mdb;User Id=sa;Password=sa;”
-
Oracle链接字符串:“USER ID=sa;DATA SOURCE=192.168.0.2/ax_log;PASSWORD=sa”
ConnectionStringBuilder
如果记不住连接字符串的格式可以使用ConnectionStringBuilder对象生成
sqlserver:
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = ".";
builder.InitialCatalog = "ax_log";
builder.UserID = "sa";
builder.Password = "sa";
Console.WriteLine(builder.ConnectionString);
结果:Data Source=.;Initial Catalog=ax_log;User ID=sa;Password=sa
mysql:
MySql.Data.MySqlClient.MySqlConnectionStringBuilder mysqlbuild = new MySql.Data.MySqlClient.MySqlConnectionStringBuilder();
mysqlbuild.Server = ".";
mysqlbuild.Database = "ax_log";
mysqlbuild.UserID = "sa";
mysqlbuild.Password = "sa";
Console.WriteLine(mysqlbuild.ConnectionString);
结果:Server=.;Database=ax_log;User Id=sa;Password=sa
Connection对象的属性
- Database: 在连接打开之后获取当前数据库的名称,或者在连接打开之前获取连接字符串中指定的数据库名。
- DataSource: 获取要连接的数据库服务器的名称。
- ConnectionTimeOut: 获取在建立连接时终止尝试并生成错误之前所等待的时间。
- ConnectionString: 获取或设置用于打开连接的字符串。
- State: 获取描述连接状态的字符串
ConnectionState
表示连接状态,它是一个枚举
//
// 摘要:
// 连接处于关闭状态。
Closed = 0,
//
// 摘要:
// 连接处于打开状态。
Open = 1,
//
// 摘要:
// 连接对象正在与数据源连接。(该值是为此产品的未来版本保留的。)
Connecting = 2,
//
// 摘要:
// 连接对象正在执行命令。(该值是为此产品的未来版本保留的。)
Executing = 4,
//
// 摘要:
// 连接对象正在检索数据。(该值是为此产品的未来版本保留的。)
Fetching = 8,
//
// 摘要:
// 与数据源的连接中断。只有在连接打开之后才可能发生这种情况。可以关闭处于这种状态的连接,然后重新打开。(该值是为此产品的未来版本保留的。)
Broken = 16
Command
Connection对象只是给我们建立了一个连接数据源的通道,但是要执行什么操作应该怎么办呢? 这个时候就要用到Command对象了。跟Connection一样,不同的数据源,ADO.NET提供了不同的Command对象。所有Command对象都是继承于DbCommand基类(IDbCommand接口)。DbCommand位于命名空间:System.Data.Common,同样.NET提供了四种Command对象:SqlCommand、OledbCommand、MySqlCommand、OracleCommand
Command对象几个常用的方法:
ExecuteNonQuery(): 对连接执行 Transact-SQL 语句并返回受影响的行数。返回结果:受影响的行数。
ExecuteScalar(): 执行查询,并返回查询所返回的结果集中第一行的第一列。
ExecuteReader(): 生成一个 System.Data.SqlClient.SqlDataReader对象
DataReader
使用command.ExecuteReader()方法,会返回一个DataReader对象
DataReader是一个快速的,轻量级,只读的遍历访问每一行数据的数据流。使用DataReader时,需要注意以下几点:
DataReader一次遍历一行数据,并返回一个包含列名字集合。
第一次调用Read()方法获取第一行数据,并将游标指向下一行数据。当再次调用该方法时候,将读取下一行数据。
当检测到不再有数据行时,Read()方法将返回false。
通过HasRows属性,我们知道查询结果中是否有数据行。
当我们使用完DataReader时,一定要注意关闭。SQL Server默认只允许打开一个DataReader
string connectionString = "Data Source=.;Initial Catalog=ax_log;User Id=sa;Password=sa123;";
using (SqlConnection con = new SqlConnection(connectionString))
{
con.Open();
string sql = "select id,name,loginname from table";
SqlCommand com = new SqlCommand(sql, con);
SqlDataReader dreader = com.ExecuteReader(CommandBehavior.CloseConnection);
while (dreader.Read())
{
Console.WriteLine(String.Format("{0}, {1},{2}",dreader[0], dreader[1], dreader[2]));
}
dreader.Close();
}
在这介绍一个SqlDataReader 的GetOrdinal方法:在给定列名称的情况下获取列序号。上面的示例我们也可以这样:
string connectionString = "Data Source=.;Initial Catalog=ax_log;User Id=sa;Password=sa123;";
using (SqlConnection con = new SqlConnection(connectionString))
{
con.Open();
string sql = "select id,name,loginname from table";
SqlCommand com = new SqlCommand(sql, con);
SqlDataReader dreader = com.ExecuteReader(CommandBehavior.CloseConnection);
int id = dreader.GetOrdinal("id");
int nameid = dreader.GetOrdinal("name");
int loginnameid = dreader.GetOrdinal("loginname");
while (dreader.Read())
{
Console.WriteLine(String.Format("{0}, {1},{2}",dreader[id], dreader[nameid], dreader[loginnameid]));
}
dreader.Close();
}
DataAdapter
DataAdapter首先将构造一个SelectCommand实例(本质就一个Command对象),然后检查是否打开连接,如果没有打开连接则打开连接,紧接着调用DataReader接口检索数据,最后根据维护的映射关系,将检索到得数据库填充到本地的DataSet或者DataTable中。同理,我们需要更新数据源时,DataAdatper则将本地修改的数据,跟据映射关系,构造InsertCommand,UpdateCommnad,DeleteCommand对象,然后执行相应的命令。
不同数据库对应不同的DataAdapter对象:SqlDataAdapter、MySqlDataAdapter、OledbDataAdapter、OracleDataAdapter
为什么说DataAdapter对象强大呢?
首先DataAdapter对象可以执行查询操作,严格意义上也不是执行,而是可以填充DataSet,DataTable对象,再一个DataAdapter对象可以进行批量更新和批量删除,至于批量添加我们有SqlBulkCopy对象,后面文章会介绍SqlBulkCopy对象。
填充DataTable案例
DataTable table = new DataTable();
using (var conn = new MySqlConnection("server=123.56.57.211;database=plugindb;user id=root;password=xxxx;Charset=utf8"))
{
using (var adapter = new MySqlDataAdapter("SELECT * FROM `VersionInfo`", conn))
{
adapter.Fill(table);
foreach (DataRow s in table.Rows)
{
Console.WriteLine($"Version:{ s["Version"].ToString()},AppliedOn:{s["AppliedOn"].ToString()}");
}
}
}
批量修改案例
DataTable table = new DataTable();
using (var conn = new MySqlConnection("server=123.56.57.211;database=plugindb;user id=root;password=xxxx;Charset=utf8"))
{
using (var adapter = new MySqlDataAdapter("SELECT * FROM `VersionInfo`", conn))
{
adapter.Fill(table);
//foreach (DataRow s in table.Rows)
//{
// Console.WriteLine($"Version:{ s["Version"].ToString()},AppliedOn:{s["AppliedOn"].ToString()}");
//}
table.Rows[0]["AppliedOn"] = "2021-03-04 02:00:00";
table.Rows[1]["AppliedOn"] = "2021-03-04 03:00:00";
MySqlCommandBuilder cmdBuilder = new MySqlCommandBuilder(adapter);//这行不能缺少,除非自定义Command赋值给adapter.UpdateCommand
Console.WriteLine("生成的Update语句:{0}", cmdBuilder.GetUpdateCommand().CommandText);
adapter.Update(table);//更新到数据源
table.AcceptChanges();//提交到DataTable中 提交后DataRow.RowState会修改为Unchanged
}
}