文章基于MySQL Connection/NET 手册,手册链接如下:
MySQL Connector/Net Developer Guide :: 4 Connector/Net Tutorials
开始之前,需要先添加MySql.Data引用
在using把MySql.Data,MySql.Data.MySqlClient,System.Data三个命名空间包括进来。
接下来,我们要介绍两个基础对象,MySqlConnection对象用于和数据库建立连接;MySqlCommand对象用于把SQL语句传送到数据服务器执行;
MySqlConnection对象
MySqlConnection类是用来连接MySQL数据库的,它接收一个连接用的字符串,返回一个MySqlConnection对象。
string connStr = "server = localhost; user = root; database = world; port = 3306; password = ***"
MySqlConnection conn = new MySqlConnection(connStr) ;
try{conn.Open();}
catch(Exception ex){Console.WriteLine(ex.ToString());}
MySqlCommand 对象
MySqlCommand 对象的创建
MySqlCommand对象实例化时接收两个参数:SQL语句(命令)以及和数据库的连接,即MySqlConnection连接对象。
string sql = "SELECT * from writer;" ;
MySqlCommand cmd = new MySqlCommand(sql, conn) ;
MySqlCommand 对象常用的三个执行方法
ExecuteReader
调用ExecuteReader方法来查询数据库。返回一个包含着查询结果的MySqlDataReader对象。
ExecuteNonQuery
调用ExecuteNonQuery来插入和删除数据。
ExecuteScalar
仅返回单个值
至此,整个步骤是:
- 使用账号密码等连接数据库创建MySqlConnection对象
- 将命令以及连接对象传给命令构造器MySqlCommand
- 调用命令构造器的执行方法如,executeReader
ExecuteReader 示例
MysqlCommand cmd = new MySqlCommand(sql, conn) ;
MySqlDataReader rdr = cmd.ExecuteReader();
while(rdr.Read())
{
Console.WriteLine(rdr[0] + " -- " + rdr[1]) ;
}
rdr.Close() ;
ExecuteNonQuery 示例
string sql = "INSERT INTO writer value(...)" ;
MySqlCommand cmd = new MySqlCommand(sql, conn);
cmd.ExecuteNonQuery();
ExecuteScalar 示例
sql = "SELECT COUNT(*) FROM writer;" ;
MySqlCommand cmd = new MySqlCommand(sql, conn) ;
object result = cmd.ExecuteScalar();
if(result != null)
{
int r = Convert.ToInt32(result) ;
...
}
处理解耦数据
前面介绍使用MySqlDataReader的例子中,在显式的执行Close方法之前,程序与数据库会一直保持连接状态。但是有时候我们希望仅在需要连接数据库时才连接,例如,读取数据,断开连接,处理数据,当需要再获取数据时,再打开连接重新执行以上过程。
要实现这种方法,需要先了解以下三个部分。
- 数据集 数据集是用于存储和处理数据的地方,即是DataSet类,一个DataSet对象被实例化后,可以用来处理多个表的数据。
- 数据适配器 数据适配器是连接数据集以及数据库之间的一个接口。数据适配器负责打开、关闭以及管理数据库的连接。 可以通过实例化MySqlDataAdapter对象来创建一个数据适配器。 数据适配器有两个主要的方法:
- Fill 方法 将数据库中的数据取出,装入数据集
- Update 方法将数据集中的数据定入数据库中
- 命令建造器 命令建造器是一个支持对象。命令建造器需要跟数据适配器一起协作。当一个MySqlDataAdapter被创建的时候,通常会给他一个初始的 SELECT 语句。根据这个 SELECT 语句,命令建造器可以判断出相应的 INSERT, UPDATE 和 DELETE 语句的格式。 这样,当你执行Update方法时,数据适配器就能够自动地把更改的数据更新到你的SQL数据库中去!你可以通过实例化MySqlCommandBuilder来创建一个命令建造器。
实例化 DataSet 对象
DataSet dsCountry;
...
dsCountry = new DataSet() ;
实例化 MySqlDataAdapter 对象
MySqlDataAdapter adapter ;
...
string sql = "SELECT Code, Name, HeadOfState FROM Country WHERE Continent = 'North America'" ;
adapter = new MySqlDataAdapter(sql, conn) ;
实例化 MySqlCommandBuilder 对象
一个命令建造器被创建之后,我们需要生成一些附加的语句提供给它,以用来插入、更新和删除数据。我们在这里只用最简单的一种方法:把适配器传给命令建造器。
MySqlCommandBuilder cb = new MySqlCommandBuilder(adapter) ;
把数据装入数据集
我们使用适配器的 Fill 方法来获取数据库中的数据然后装载入数据集中。 适配器会自动与数据库连接并获取数据。 第二个参数”Country”指明要装载、修改的表。
DataSet dsCountry ;
...
dsCountry = new DataSet() ;
...
daCountry.Fill(dsCountry, "Country") ;
更新数据集的数据到数据库
我们使用适配器的 Update 方法将数据集中被改变的数据写回到数据库中。
adapter.Update(dsCountry, "Country") ;
整个过程
// 创建连接实例 string connStr = "server=localhost;user=root;database=world;port=3306;password=***";
MySqlConnection conn = new MySqlConnection(connStr) ;
// 使用连接实例以及SELECT语句初始化适配器 string sql = "SELECT Code, Name, HeadOfState FROM Country WHERE Continent = 'North America'" ;
adapter = new MySqlDataAdapter (sql, conn) ;
// 使用适配器初始化命令建造器 MySqlCommandBuilder cb = new MySqlCommandBuilder(adapter) ;
// 创建数据集 DataSetCountry = new DataSet();
// 把数据库中的 Country 表加载进数据集 adapter.Fill(DataSetCountry, "Country") ;
// 设置控件dataGridView的数据来源 dataGridView1.DataSource = DataSetCountry ;
dataGridView1.DataMember = "Country" ;
adapter.Update(DataSetCountry, "Country") ;
处理参数
为了防止SQL注入,我们可以使用带参数的SQL命令,然后再把参数值附加到命令构造器中去。
SQL 注入例子:
假设我们有两行代码,他的作用是从文本框中获取用户的名字,然后查找writer表下有关这个名字的记录,如下:
name = TextBox1.Text ; sql = "SELECT * FROM writer WHERE NAME = " + name ;
那么会出现一个问题,就是一个恶意用户可能在TextBox1中直接输入SQL代码,例如:
"Whatsoever ; DELETE * FROM writer"
那么最终sql变成了:
"SELECT * FROM writer WHERE NAME = Whatsoever ; DELETE * FROM writer"
如果我们执行这条语句,writer 表就会被清空。
首先在执行的SQL语句中,对每一个参数我们都用’@’加上一个参数名来代替。例如:
string sql = SELECT * FROM writer WHERE NAME = @name" ;
然后在命令构造器中绑定参数:
cmd.Parameter.AddWithValue("@name", TextBox1.Text) ;
其实我们可以看到,这种做法相当于使用SQL中的变量。我们的SQL语句中指定NAME等于@name变量,接着我们使用AddWithValue来创建一个@name变量,将TextBox1.Text的值传递给@name变量。这样当我们执行SQL语句时,@name的就被正确的赋值了。
处理存储过程
调用存储过程的代码如下:
string rtn = "country_hos" ;
MySqlCommand cmd = new MySqlCommand(rtn, conn) ;
cmd.CommandType = CommandType.StoredProcedure ;
首先在第一条语句中,country_hos是我们要调用的存储过程的名字。
接着第二句中,我们把这个存储过程的名字(或者说命令)传送给命令构造器,以实例化一个命令构造器。
最后在第三句中,我们在这个命令构造器中指定命令的类型为调用存储过程。
对于要传递给调用例程的参数,我们使用上一小节“处理参数”中的方法:
cmd.Parameter.AddWithValue("@con", "Europe") ;
到这里,我们就可以通过之前学的三个执行方法去执行命令了。例如, ExecuteReader() 方法
示例代码
MySqlConnection conn = new MySqlConnection("server=localhost;user=root;database=world;port=3306;password=***");
try
{
conn.Open() ;
MySqlCommand cmd = MysqlCommand("country_hos", conn) ;
cmd.CommandType = CommandType.StoredProcedure ;
cmd.Parameter.AddWithValue('@con', 'Europe') ;
MySqlDataReader rdr = cmd.ExecuteReader() ;
while(rdr.Read())
Console.WriterLine(rdr[0] + " --- " + rdr[1]) ;
rdr.Close() ;
}
catch(Exception ex) { // } conn.Close() ;
使用 MySqlScript来执行多语句脚本
MySqlScript 类允许你执行一连串的SQL语句。 它的使用跟命令建造器很相似:
1. 创建Connection连接
2. 根据连接及语句创建MySqlScript
3. MySqlScript实例调用Execute方法来执行SQL语句
string sql = "SELECT * FROM TestTable" ;
...
// 直接用sql和conn创建MySqlScript MySqlScript script = new MySqlScript(conn, sql) ;
...
// 也可以直接先实例化MySqlScript,然后再用 // script.Query 指定 sql // script.Connection 指定 conn MySqlScript script = new MysqlScript() ;
script.Query = sql ;
script.Connection = conn ;
...
script.Execute() ;
MySqlScript类中有几个相关的事件。
- Error – 如果有错误发生,则发出此事件
- ScriptCompleted – 如果脚本成功执行,则发出此事件
- StatementExecuted – 每一条语句执行成功,都发出一个这个事件
我们可以为这些事件绑定回调函数。
script.Error += new MySqlScriptErrorEventHandler(script_Error);
script.ScriptCompleted += new EventHandler(script_ScriptCompleted);
script.StatementExecuted += new MySqlStatementExecutedEventHandler(script_StatementExecuted);
static void script_StatementExecuted(object sender, MySqlScriptEventArgs args)
{
Console.WriteLine("script_StatementExecuted");
}
static void script_ScriptCompleted(object sender, EventArgs e)
{
/// 因为脚本执行成功,所以这里EventArgs e 等于 EventArgs.Empty Console.WriteLine("script_ScriptCompleted!");
}
static void script_Error(Object sender, MySqlScriptErrorEventArgs args)
{
Console.WriteLine("script_Error: " + args.Exception.ToString());
}
设置分隔符
我们知道在执行一个过程时,我们需要先把分隔符设置为其它分隔符(非分号),然后在过程语句最后再把分号设置回来作为分隔符。 我们可以通过调用script.Delimiter = “??” 实现。在这里??是新的分隔符。例如:
MySqlScript script = new MySqlScript(conn, sql) ;
script.Delimiter = "??" ;
script.Execute() ;
script.Delimiter = ";" ;
—————————–
如果你看到这了,就点个赞再走呗?