C# - MySQL数据库编程 简明教程

文章基于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

仅返回单个值

至此,整个步骤是:

  1. 使用账号密码等连接数据库创建MySqlConnection对象
  2. 将命令以及连接对象传给命令构造器MySqlCommand
  3. 调用命令构造器的执行方法如,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类中有几个相关的事件。

  1. Error – 如果有错误发生,则发出此事件
  2. ScriptCompleted – 如果脚本成功执行,则发出此事件
  3. 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 = ";" ;

—————————–

如果你看到这了,就点个赞再走呗?

    原文作者:李展发
    原文地址: https://zhuanlan.zhihu.com/p/28401873
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞