B7第七章第 1 节: ADO.Net简介
第七章第 1 节: ADO.Net简介
MYSQL的.Net驱动mysql-connector-net-***.msi下载地址:
1)http://www.cncrk.com/downinfo/41149.html
2)http://www.cr173.com/soft/50789.html
3)http://dev.mysql.com/downloads/file.php?id=405442
4)http://download.csdn.net/detail/du_niao/6500785
新建项目,添加引用→“扩展”,添加Mysql.Data;如果是直接解压版,然后直接添加对MySql.Data.dll文件的引用;
123456789
using (MySqlConnection conn =    new MySqlConnection("Server=localhost;Database=study1;uid=root;pwd=root;Charset=utf8"))
using (MySqlCommand cmd = conn.CreateCommand())
{
conn.Open();//一定要在执行前Open数据库连接
cmd.CommandText = "Insert into T_Users(UserName,Password) values('中国人','123')";
int rowCount = cmd.ExecuteNonQuery();
Console.WriteLine("受影响的行数"+rowCount);
}
解释一下代码:
MySqlConnection、MySqlCommand实现了IDisposable接口,因此使用using进行资源释放;
"Server=localhost;Database=study1;uid=root;pwd=root;Charset=utf8"叫连接字符串,Server是Mysql服务器的地址,Database是连接的数据库,uid、pwd是用户名和密码,采用utf8编码。
conn.Open():在执行MySqlCommand之前一定要先打开数据库连接,否则会报错。
ExecuteNonQuery是执行Update、Insert、Delete等非查询语句,返回值为受影响的行数。
*************************************************************************************
using(MySqlCommand cmd = conn.CreateCommand())
{
      conn.Open();//一定要在执行前打开Open数据库连接
}
解释语法:: 创建一个到数据库执行命令的对象,即:MySqlCommand;
从conn  的  CreateCommand() 创建 MySqlCommand 对象【 推荐用这样的语法,比较简单】
B7第七章 第 2 节: 执行Insert语句
第七章 第 2 节: 执行Insert语句
1 using (MySqlConnection conn = 2 3 new MySqlConnection("Server=127.0.0.1;Database=study1;uid=root;pwd=root;Charset=utf8")) 4 5 using(MySqlCommand cmd = conn.CreateCommand()) 6 7 { 8 9 conn.Open(); 10 11 cmd.CommandText = "Insert into T_Users(UserName,Password) values('如鹏网','123')"; 12 13 int rc = cmd.ExecuteNonQuery(); 14 15 Console.WriteLine("插入成功,影响行数"+rc); 16 17 }
ExecuteNonQuery是执行Update、Insert、Delete等非查询语句,返回值为受影响的行数。
B7第七章 第 3 节: ExecuteScalar的用法
第七章 第 3 节: ExecuteScalar  【【【【ExecuteScalar:执行查询,并返回查询所返回的结果集中第一行的第一列,忽略其他行列。一般用来简单的获得只有【【一行一列】】的查询结果的值。】】】】 案例1: cmd.CommandText = "Select count(*) from T_Users"; long count = (long)cmd.ExecuteScalar();//这样会产生错误--------int count = (int)cmd.ExecuteScalar();。。类型转换有问题,,可以通过。。断点调试看见cmd(long) long count =Convert.ToInt64 (cmd.ExecuteScalar());//这样写确保数据类型范围足够大。转化不出错 案例2: cmd.CommandText = "Select Password from T_Users where UserName='admin'"; string pwd = (string)cmd.ExecuteScalar(); if (string.IsNullOrEmpty(pwd)) { Console.WriteLine("找不到admin"); } else { Console.WriteLine("admin的密码:" + pwd); } ************************************************************************************************************************************* using MySql.Data.MySqlClient; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Test数据库ExecuteScalar { class Program { static void Main(string[] args) { using(MySqlConnection conn =new MySqlConnection("Server=localhost;Database=study;uid=root;pwd=root;CharSet=utf8")) using (MySqlCommand cmd = conn.CreateCommand()) { /* conn.Open(); cmd.CommandText = "select count(*) from t_users"; // long count = (long)cmd.ExecuteScalar(); //ExecuteScalar:执行查询,并返回查询所返回的结果集中第一行的第一列, //忽略其他行列。一般用来简单的获得只有一行一列的查询结果的值。 long count = Convert.ToInt64(cmd.ExecuteScalar()); Console.WriteLine("一共有"+count+"记录"); */ conn.Open();//只能适合查询只有返回结果为一行一列的查询比较好用这个 cmd.CommandText = "Select Password from T_Users where UserName='admin'"; string pwr = (string)cmd.ExecuteScalar(); if (string.IsNullOrEmpty(pwr)) { Console.WriteLine("找不到admin"); } else { Console.WriteLine("admin的密码是"+pwr); } Console.ReadKey(); } } } }
B7第七章 第 4 节: ExecuteReader
1 第七章 第 4 节: ExecuteReader 2 using MySql.Data.MySqlClient; 3 using System; 4 using System.Collections.Generic; 5 using System.Linq; 6 using System.Text; 7 using System.Threading.Tasks; 8 9 namespace TestMysql__ExecuteReader 10 { 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 //不要漏输入东西 16 using(MySqlConnection conn=new MySqlConnection("Server=127.0.0.1;Database=study;uid=root;pwd=root;Charset=utf8;")) 17 using (MySqlCommand cmd = conn.CreateCommand()) 18 { 19 conn.Open();//连接必须先打开数据库 20 cmd.CommandText = "Select * from T_Users"; 21 using (MySqlDataReader reader = cmd.ExecuteReader()) 22 { 23 while (reader.Read())//如果记录不为空,就返回true 24 { 25 // long id = reader.GetInt64(0);//通过数据库中的列号,从0开始,获取主键列的序列号 26 long id = reader.GetInt64("id");//通过数据库中的列名字,获取主键列的序列号 27 string username = reader.GetString(1);//获取姓名列的值 28 29 string password = reader.GetString("password");//获取密码列的字符串 30 Console.WriteLine("Id=" + id + ";UserName=" + username + ";PassWord=" + password); 31 } 32 Console.WriteLine(); 33 int ordNumber = reader.GetOrdinal("username");//通过列明字获取,列明的序列号 34 Console.WriteLine("UserName是数据库中的第" + ordNumber + "列;"); 35 } Console.ReadKey(); 36 } 37 } 38 } 39 }
B7第七章 第 5 节: SQL注入漏洞说明
第七章 第 5 节: SQL注入漏洞说明
select count(*) from t_users
where UseName="username" and Password="password"
密码输入:a' or ' a'='a
B7第七章 第 7 节: 参数化查询2
第七章 第 7 节: 参数化查询2
1、参数化查询有点:安全;效率高(SQL预编译);
2、所有的sql中都可以使用参数化查询传递;表名,字段名等不能用参数化进行替换;
3、陷阱:不要用MySqlParameter(string  parameterName,object value )的这个构造函数,因为(“Age”,0)会被匹配成MySqlParameter(string  parameterName,MySqlType dbType)这个构造函数
/*
using(MySqlConnection conn = new MySqlConnection("Server=127.0.0.1;Database=study1;uid=root;pwd=root;Charset=utf8"))
using (MySqlCommand cmd = conn.CreateCommand())
{
    conn.Open();
    cmd.CommandText = "Insert into @p(UserName,Password) values(@un,@pwd)";//;表名,字段名等不能用参数化进行替换;
    cmd.Parameters.Add(new MySqlParameter { ParameterName = "@p", Value = "t_users" });//;表名,字段名等不能用参数化进行替换;
    cmd.Parameters.Add(new MySqlParameter { ParameterName="@un",Value="rupeng"});
    cmd.Parameters.Add(new MySqlParameter { ParameterName="@pwd",Value="123456"});
    cmd.ExecuteNonQuery();
}*/
 
/*
using(MySqlConnection conn = new MySqlConnection("Server=127.0.0.1;Database=study1;uid=root;pwd=root;Charset=utf8"))
using (MySqlCommand cmd = conn.CreateCommand())
{
    conn.Open();
    cmd.CommandText = "Insert into T_Users(UserName,Password,Age) values(@un,@pwd,@Age)";
    cmd.Parameters.Add(new MySqlParameter("@un","test1"));
    cmd.Parameters.Add(new MySqlParameter("@pwd", "321"));
 
    //int i = 0;
    //cmd.Parameters.Add(new MySqlParameter("@Age", i));//正确写法1
// cmd.Parameters.Add(new MySqlParameter("@Age", 0));//错误的写法;有陷阱0
    cmd.Parameters.Add(new MySqlParameter("@Age",(object)0));//正确写法2
    cmd.ExecuteNonQuery();
}*/
B7第七节第 8 节: 读取数据库中的null值
1 第七节第 8 节: 读取数据库中的null值 2 3 使用IsDBNull获取指定序号的列的值是否为null 4 5 int? age=null; 6 7 if (!reader.IsDBNull(reader.GetOrdinal("Age"))) 8 9 { 10 11 age = reader.GetInt32("Age"); 12 13 } 14 15 16 using MySql.Data.MySqlClient; 17 using System; 18 using System.Collections.Generic; 19 using System.Linq; 20 using System.Text; 21 using System.Threading.Tasks; 22 23 namespace TestMysql__读取数据库中的null值 24 { 25 class Program 26 { 27 static void Main(string[] args) 28 { 29 using(MySqlConnection conn=new MySqlConnection("server=127.0.0.1;database=study;uid=root;pwd=root;Charset=utf8")) 30 using (MySqlCommand cmd = conn.CreateCommand()) 31 { 32 conn.Open(); 33 cmd.CommandText = "select * from t_users "; 34 using (MySqlDataReader reader = cmd.ExecuteReader()) 35 { 36 while (reader.Read())//如果记录不是null或者为“”就返回true,转到定义 37 { 38 string username = reader.GetString("username"); 39 //string password = reader.GetString("password");//这样写的话,当密码为空值的时候,会导致,调试错误 40 string password; 41 if (reader.IsDBNull(reader.GetOrdinal("password")))//获取密码列的列的数值 42 { 43 password = null; 44 } 45 else 46 { 47 //GetString/GetInt32 无法读取数据库中的null值 48 //需要提前用IsDBNull判断 49 password = reader.GetString("password"); 50 } 51 int? Age;//若果使用"int?"类型则可以将int类型,转化为null 52 if (reader.IsDBNull(reader.GetOrdinal("Age"))) 53 { 54 Age = null; 55 } 56 else 57 { 58 Age = reader.GetInt32("age"); 59 } 60 Console.WriteLine("用户名:" + username + ";密码:" + 61 (password==null?"密码为空":password)+"年龄:"+(Age==null?"年龄没有记录":Age.ToString())); 62 //使用了双目运算; 条件?回答1:回答2 “ : ”两边的数据类型要一致 63 64 } 65 66 } Console.ReadKey(); 67 } 68 69 70 } 71 } 72 }
B7第七章 第 9 节: 离线结果集入门
1 =第七章 第 9 节: 离线结果集入门 2 1、DataReader是服务器结果集游标的体现,所有查询出来的数据都在MySQL服务器上。好处是:当查询结果数据量大的时候避免占用本地内存。不过大部分项目中都会避免大查询结果,因此缺点就明显了:读取的时候必须保持Connection,不仅用起来麻烦,而且会较长时间占用MySQL服务器的连接资源。 3 4 2、DataSet是一个离线结果集容器,它把结果数据放到本地内存中。因为查询结果可能会包含多个表,因此DataSet包含若干DataTable(ds.Tables)、DataTable包含若干DataRow(dt. Rows)。 5 6 用法1: 7 8 9 DataSet ds = new DataSet(); 10 MySqlDataAdapter adapter = new MySqlDataAdapter(cmd); 11 adapter.Fill(ds); 12 DataTable table = ds.Tables[0]; 13 14 15 DataSet 可以盛放多个查询结果集到DataTable ;DataAdapter还可以对结果进行傻瓜化更新、删除、修改。我们一般查询结果集就一个DataTable, DataAdapter的傻瓜化更新不适合于正式的项目,因此有更简单的用法 16 17 DataTable dt = new DataTable(); 18 19 dt.Load(reader); 20 21 把DataTable声明到using外,using外再使用查询结果。 22 23 遍历DataTable: 24 25 for (int i = 0; i < dt.Rows.Count; i++) 26 { 27 DataRow row = dt.Rows[i]; 28 string name = row.IsNull("Name")?null:(string)row["Name"];//NULL处理 29 Console.WriteLine("name"+name); 30 } 31 32 33 案例代码: 34 35 36 /* 37 using (MySqlConnection conn =new MySqlConnection("Server=127.0.0.1;Database=study1;uid=root;pwd=root;Charset=utf8")) 38 39 using (MySqlCommand cmd = conn.CreateCommand()) 40 { 41 conn.Open(); 42 cmd.CommandText = "select * from t_users"; 43 using (MySqlDataReader reader = cmd.ExecuteReader()) 44 { 45 DataTable dt = new DataTable(); 46 dt.Load(reader); 47 for (int i = 0; i < dt.Rows.Count; i++) 48 { 49 DataRow row = dt.Rows[i]; 50 int id = (int)row["Id"];//下标方式获得是object 51 string username = (string)row["UserName"]; 52 53 //做很复杂的io操作,把username存到文件中 54 //这样就会长期占据Connection 55 56 // object obj = row["Password"]; 57 //if(row["Password"]==DBNull.Value)//返回的不是null,而是DBNull 58 59 //string password = (string)row["Password"]; 60 //int age = (int)row["Age"]; 61 string password = row.IsNull("Password") ? null : (string)row["Password"]; 62 int? age = row.IsNull("Age") ? (int?)null : (int)row["Age"]; 63 64 Console.WriteLine("id=" + id + ";Username=" + username 65 +";username="+username+";age="+age); 66 } 67 } 68 }*/ 69 70 /* 71 DataTable table = new DataTable(); 72 using (MySqlConnection conn = 73 new MySqlConnection("Server=127.0.0.1;Database=study1;uid=root;pwd=root;Charset=utf8")) 74 using (MySqlCommand cmd = conn.CreateCommand()) 75 { 76 conn.Open(); 77 cmd.CommandText = "select * from t_users"; 78 using (MySqlDataReader reader = cmd.ExecuteReader()) 79 { 80 table.Load(reader);//加载到table中 81 } 82 } 83 84 for (int i = 0; i < table.Rows.Count; i++) 85 { 86 DataRow row = table.Rows[i]; 87 int id = (int)row["id"]; 88 string username = (string)row["UserName"]; 89 Console.WriteLine(id+":"+username); 90 } 91 */
B7第七章 第 12 节: 实现MysqlHelper
第七章 第 12 节: 实现MysqlHelper 复习前边的知识:: public static void ( int ,params string[ ] strs ) params 关键字前边可以有其他参数,params,必须放在参数的最后一个前面【目的就是该参数可以写,也可以也很多个】,但是,但是调用的时候。前边非可变长度的参数,必须赋值了,才可以调用。。。。 连接字符串一般配置到App.config(网站是Web.config)中的<connectionStrings>段中 使用ConfigurationManager类(添加对System.Configuration的引用)【引用程序集System.Configuration】读取 string connstr =ConfigurationManager.ConnectionStrings["connstr"].ConnectionString 一定要保证【代码中的名字】和【配置文件中的名字】一致(初学者容易犯错的,一般提示“初始化代码错误”这个错误就是因为两者名字不一致造成的) using MySql.Data.MySqlClient; using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ADONETTest2 { class MySqlHelper { private static readonly string connstr =ConfigurationManager.ConnectionStrings["connstr"].ConnectionString;//静态方法初始化字符串connstr public static MySqlConnection CreateConnection()//通过该方法建立与Mysql数据库的连接,只要是一用该方法就实现了链接数据库 { //using (MySqlConnection conn = new MySqlConnection(connstr))//这里千万不要使用使用using进行资源的释放,, MySqlConnection conn = new MySqlConnection(connstr);//建立连接 conn.Open();//打开数据库 return conn;//返回值 为连接conn } public static int ExecuteNonQuery(MySqlConnection conn, string sql, params MySqlParameter[] parameters)//引用已经建立的连接,执行sql语句,返回影响的行数 { using (MySqlCommand cmd = conn.CreateCommand())//用using释放查询语句的资源 { cmd.CommandText = sql;//引用sql语句 /* foreach (MySqlParameter p in parameters)//foreach数组遍历;用法:"[ ]"前的数据类型名字 +p+ 关键字in+数组名字parameters { cmd.Parameters.Add(p); }*/ cmd.Parameters.AddRange(parameters);//只要是集合类的都包含此方法AddRange() return cmd.ExecuteNonQuery();//返回该语句cmd影响的行数 } } public static int ExecuteNonQuery(string sql,params MySqlParameter[] parameters)//引用方法内自己建立的连接,执行sql语句,返回影响的行数 { using (MySqlConnection conn(****) = CreateConnection())//用using释放方法内自己建立的连接 { return ExecuteNonQuery(conn, sql, parameters);//引用上边代码的第二个方法,此时引用的已建立的连接是这个(****)位置的连接,接着返回影响的行数 } } public static object ExecuteScalar(MySqlConnection conn, string sql,params MySqlParameter[] parameters)//引用已经建立的连接,执行sql语句,返回一行一列的值 { using (MySqlCommand cmd = conn.CreateCommand()) { cmd.CommandText = sql; cmd.Parameters.AddRange(parameters); return cmd.ExecuteScalar(); } } public static object ExecuteScalar(string sql,params MySqlParameter[] parameters)//引用方法内自己建立的连接,执行sql语句,返回一行一列的值 { using (MySqlConnection conn = CreateConnection()) { return ExecuteScalar(conn, sql, parameters); } } public static DataTable ExecuteQuery(MySqlConnection conn, string sql,params MySqlParameter[] parameters)//引用已经建立的连接,执行sql语句,返回多行多列的值到一个DataTable中 { DataTable table = new DataTable(); using (MySqlCommand cmd = conn.CreateCommand()) { cmd.CommandText = sql; cmd.Parameters.AddRange(parameters); using (MySqlDataReader reader = cmd.ExecuteReader()) { table.Load(reader); } } return table; } public static DataTable ExecuteQuery{+++}(string sql,params MySqlParameter[] parameters)//引用方法内自己建立的连接,执行sql语句,返回多行多列的值到一个DataTable中 { using (MySqlConnection conn = CreateConnection()) { return ExecuteQuery(conn, sql, parameters);//引用{+++}的方法 } } } } 注意:(****)、{+++}为标记符号。。ExecuteQuery意思是 执行查询 返回值是 一张二维表,,,ExecuteNonQuery意思是 执行非查询,即:插入,更新,删除操作 返回值是影响的行数,即整形 int
B7第七章 第 13 节: 获得自动增长字段的值
1 第七章 第 13 节: 获得自动增长字段的值 2 1、使用LAST_INSERT_ID()获取“最后一次插入的自动递增列的值” 3 4 2、需要注意Insert语句和select LAST_INSERT_ID()一定要在要在同一个连接中。 5 6 7 using (MySqlConnection conn = MySqlHelper.CreateConnection()) 8 { 9 MySqlHelper.ExecuteNonQuery(conn, 10 "insert into t_users(UserName,Password) values('我几时我','123')"); 11 object o = MySqlHelper.ExecuteScalar(conn, "select Last_Insert_Id()"); 12 //Last_Insert_Id()是获取当前连接中,最近一次自动递增字段的值 13 ulong id = (ulong)o;//无符号的long 14 Console.WriteLine(id); 15 } 16 可以Insert、LAST_INSERT_ID()在同一个连接中单独执行,也可以把LAST_INSERT_ID()放到insert语句后面用;分割(使用ExecuteScalar执行即可) 17 18 1 19 2 20 ulong id = (ulong)MySqlHelper.ExecuteScalar("insert into t_users(UserName,Password) values('我几时我','123');select last_insert_id()"); 21 Console.WriteLine(id);
B7第七章 第 14 节: 事务的原子性
第七章 第 14 节: 事务的原子性
1、using 相当于tyr......finally 
2、捕获异常需要try.......catch
事务的几个关键环节:
1)要在一个连接中;
2)启动事务:MySqlTransaction tx = conn.BeginTransaction();
3)操作结束后执行tx.Commit() 提交事务;
4)如果执行出错,则tx.Rollback()回滚(当前事务的操作全部取消)。
using(MySqlConnection conn=MysqlHelper.CreateConnection()) using(MysqlTransaction tx = conn.BeginTransaction()) { try { MysqlHelper.ExecuteNonQuery(conn, "Update t_employees Set salary=salary-100 where name="Tom""); string s = null;//用于制造异常 s.ToString(); MysqlHelper.ExecuteNonQuery(conn, "Update t_employees Set salary=salary+100 where name="John""); tx.Commit();//提交全部成功 } catch (Exception ex)//此处的括号可以省略不写,但是一样 { tx.Rollback();//发生异常,所有的操作都进行回滚,全部还原回去 console.WriteLine(ex);//打印出异常 } }
B7第七章第 23 节: ADO.Net连接SQLServer(SoEasy)
第七章第 23 节: ADO.Net连接SQLServer(SoEasy)
1、ADO.Net如何连接SQLServer:SQLServer驱动.Net内置(亲生的);把MySqlConnection换成SqlConnection,MySql***换成Sql***。
2、连接字符串:
server=ip;user id=sa;password=密码;database=db1
3、SQLHelper:把MySql查找替换成Sql就可以了。
4、获得自动增长列的值:Insert into t1(...) output inserted.Id values(.........)
5、(*)如果基于接口编程,只要改动CreateConnection就可以(查询参数以Dictionary<string,object>传递;如果使用Provider,连代码都不用改,改配置文件即可。
6、需要特别注意:SqlServer的事务和mysql事务使用有一点不一样的地方是“需要把BeginTransaction返回的SqlTransaction对象赋值给SqlCommand的Transaction属性”
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号