考前复习

ExecuteNonQuery():执行 SQL 语句并返回受影响的行数
 
ExecuteReader():执行 SQL 语句并返回一个 SqlDataReader 对象
 
ExecuteScalar():执行 SQL 语句并返回查询结果的第一行的第一列的值,忽略其他列或行的值
 
对于 ExecuteNonQuery()方法,我们已经学习过,是用于实现非查询 SQL 命令的执行。另外,两个
方法,其实都用于查询之中。先看 ExecuteScalar()方法,它是用于执行查询 SQL 命令,并可以返回查
询结果第一行第一列的值
 
以查询数据表中电影的总数量为例,来看 ExecuteScalar()方法的使用,具体代码如下:
 
// 查询电影数量的SQL语句 
string sql = "select count(*) from FilmInfo"; // 连接字符串 
string conStr = "server=.;database=FilmDB;uid=sa;pwd=123456;"; 
// 创建连接对象 
SqlConnection conn = new SqlConnection(conStr); // 打开连接 
conn.Open(); // 创建Command对象 
SqlCommand cmd = new SqlCommand(sql, conn); 
// 查询首行首列 
int number = (int)cmd.ExecuteScalar(); // 输出结果 
Console.WriteLine("一共有{0}部电影!",number); // 关闭连接 
conn.Close(); 
Console.ReadKey();
这个案例中,关键代码为:int number = (int)cmd.ExecuteScalar(),通过 Command 对象来调用
ExecuteScalar()方法得到查询结果中首行首列的值。而查询语句 select count(*) from FilmInfo 只
返回了一个表示数量的整数值,所以适合使用该方法。还有一点,这里对查询的结果进行了强制类型转
换。这是因为 ExecuteScalar()方法默认返回结果为 Object 类型,我们根据查询结果可以转成其它相
应类型。需要注意的是,ExecuteScalar()方法执行的 SQL 语句也许并不都能够得到我们想要的结果,
因此在进行类型转换的时候很容易出错,在使用的时候需要尤其小心。

二、DataReader

2.1、简介

DataReader 对象的作用是以流的方式从数据源读取数据,但是在读取的时候它只能够以只进的方
式读取,并且一次只能够读取一行数据。比如数据源中有 10 条数据,它就只能够从前往后读取,如果
读取了第 5 条数据后再想查看第 1 条数据,那就只能够重新创建 DataReader 对象。另外,该对象只能
够读取数据,也就是说是只读的,如果要修改数据,就不能够使用 DataReader 对象了。
 
DataReader 对象的这种读取方式使得它具有了很多有趣的特性。首先,DataReader 对象读取数据
的操作是一个持续的过程,因此为它提供连接服务的 Connection 对象就无法再执行其他任何操作,除
非将 DataReader 对象关闭,否则这个状态将会一直持续。其次,DataReader 对象并不关心数据行的
多少,它一次只能够读取一行,通过循环就能读取大量的数据。
 
简单总结起来,DataReader 对象进行查询有如下的特点:
  •  DataReader 是只读只进的数据流;
  •  使用 DataReader 读取数据的过程,始终需要与数据库保持连接;
  •  每次只能读取一行数据,通过循环可以读取多行数据。
下面是 ADO.NET 部分对象模型图,图中显示了 DataReader 对象的作用:
 
ADO.NET第三章:DataReader
趣味理解,应用程序从数据库中查询数据,就像从仓库运送货物到码头一样,两个地方首先要有一
条通路,这是 Connection 连接对象;也要有一辆货车,这就是 DataReader 对象,负责运送货物;货车
上到底装了多少货物,取决于老板给你的指令,这就是 Command 对象。货车要在路上跑的时候,仓库和
码头之间的路要一直通着。

2.2、创建 DataReader 对象

DataReader 对象也会根据数据提供程序的不同而有所区别,而用于 SQL Server 的就是
SqlDataReader 对象,这里我们对 SqlDataReader 进行学习。
 
SqlDataReader 类所在的命名空间为 System.Data.SqlClient,它本身没有任何的构造函数,所以
不能用new关键字来创建对象了。创建SqlDataReader对象必须调用SqlCommand对象的ExecuteReader() 
方法,如下代码所示:
SqlDataReader dr = cmd.ExecuteReader(); // cmd是可用的Command对象
创建出 SqlDataReader 对象后,才能去进行数据的读取。

2.3、常用方法

SqlDataReader 对象是一个轻量级的数据读取对象,常用到的方法有两个,如表 3-2 所示: 
ADO.NET第三章:DataReader
Read()方法的作用是读取下一条记录,SqlDataReader 对象的默认位置在第一条记录前面。因此,
必须调用 Read()方法来开始访问数据。Read()方法返回结果为布尔类型,以确定是否还存在数据行,
如果返回值为 true,表示存在数据行;返回值为 false,表示已经没有数据行了。
 
Close()方法则用于关闭 SqlDataReader 对象,对于每个关联的 SqlConnection 对象,一次只能打
开一个 SqlDataReader 对象,直到调用其 Close()方法之前,打开另一个的任何尝试都将失败,因此
SqlDataReader 对象在使用完毕后一定不要忘记关闭。
 
由于SqlDataReader对象一次只能够读取一行数据,因此在使用的时候一般都是跟循环结构,尤其
是 while 循环配合一起使用,通过 Read()方法就可以确定是否还有数据行读取,而在循环结构结束后
关闭 SqlDataReader 对象。基本代码如下:
while(dr.Read()) // dr是可用的SqlDataReader对象,通过循环进行数据读取
{
// 读取数据
}
dr.Close(); // 关闭SqlDataReader对象
如果是特殊情况,查询结果最多只有一行数据时,可以把循环改成 if 语句,只读一次即可。剩下
的问题就是在循环中完成数据读取及数据显示的工作了。

2.4、读取数据

假设执行的查询语句是:select * from FilmInfo,在 SQL Server 中可以得到如下查询结果: 
ADO.NET第三章:DataReader
我们在应用程序中如何将数据读取出来呢?SqlDataReader 对象提供了很多用来读取数据的方法,
但是最常用的是通过下标来读取数据。 以图 3-4 的查询结果为例,表示每列数据下标的方法有两种:
 
1、 使用数字下标:
数字下标从 0 开始,第一列下标为 0,第二列下标为 1,依此类推。使用数字下标读取列数据
的代码如下: 
 int ID = (int)dr[0]; // 编号 
string name = dr[1].ToString(); // 电影名称 
string typeName = dr[2].ToString(); // 电影类型 
string actors = dr[3].ToString(); // 演员列表 
int amount = (int)dr[4]; // 库存数量 
decimal price = (decimal)dr[5]; // 价格 
string desc = dr[6].ToString(); // 描述
2、使用字段名称下标:
还可以使用字段名称即列名作为下标,代码如下:
int ID = (int)dr["ID"];
// 编号
string name = dr["Name"].ToString();
// 电影名称
string typeName = dr["TypeName"].ToString(); // 电影类型
string actors = dr["Actors"].ToString();
// 演员列表
int amount = (int)dr["Amount"];
// 库存数量
decimal price = (decimal)dr["Price"];
// 价格
string desc = dr["Desc"].ToString();
// 描述
说明:代码中的 dr 为 SqlDataReader 对象。
 
无论采用哪种方式,其中括号“[]”中所使用的下标或者字段名称都是以SQL查询语句的执行结果
为依据。虽然两种方式的效果是一样的,但是通过字段名称作为下标来读取数据会更加安全一些。还
有,默认时候读取出来的数据是 Object 类型,所以通常需要进行类型转换,一定要注意类型转换是否
正确。 

三、案例

3.1、查询全部电影信息 

static void Main(string[] args) { // 连接字符串 
 string conStr = "server=.;database=FilmDB;uid=sa;pwd=123456;"; 
 // 查询所有电影信息的SQL语句 
 string sql = " select * from FilmInfo "; 
 // 创建Connection对象 
SqlConnection conn = new SqlConnection(conStr); 
// 打开连接 
 conn.Open(); 
// 创建Command对象 
 SqlCommand cmd = new SqlCommand(sql, conn); 
 // 创建DataReader对象 SqlDataReader dr = cmd.ExecuteReader(); 
 Console.WriteLine("============ 所有电影信息如下 ============"); // 通过循环读取所有数据 while (dr.Read()) 
 { 
 // 读取每列的值 
 int ID = (int)dr[0]; 
 string name = dr[1].ToString(); 
 string typeName = dr[2].ToString(); 
 string actors = dr[3].ToString(); 
 int amount = (int)dr[4]; 
 decimal price = (decimal)dr[5]; 
 string desc = dr[6].ToString(); 

 // 输出 
 Console.WriteLine("电影编号:{0}", ID); 
 Console.WriteLine("电影名称:{0}", name); 
 Console.WriteLine("电影类型:{0}", typeName); 
 Console.WriteLine("演员列表:{0}", actors); 
 Console.WriteLine("库存数量:{0}", amount); 
 Console.WriteLine("价格:{0}", price); 
 Console.WriteLine("描述:{0}", desc); 
 Console.WriteLine("------------------------------------"); 
 } // 关闭DataReader对象 
 dr.Close(); 
// 关闭连接 
 conn.Close(); 
 Console.WriteLine("\n恭喜,查询完成!"); 
 Console.ReadKey(); }

3.2.根据编号查询某部电影信息 

这是查询部分电影信息,我们的 SQL 语句需要加上 where 子句。如果是这样,查询过程又可能有什
么变化呢?下面来看根据电影编号进行查询某部电影信息的案例: 
 
static void Main(string[] args) 
 { 
 Console.Write("输入要查询电影的编号:"); 
 int id = int.Parse(Console.ReadLine()); // 连接字符串 
 string conStr = "server=.;database=FilmDB;uid=sa;pwd=123456;"; 
// 根据编号查询电影的SQL语句 
 string sql = string.Format("select * from FilmInfo where ID='{0}'",id); 
// 创建Connection对象 
 SqlConnection conn = new SqlConnection(conStr); 
// 打开连接 
 conn.Open(); 
// 创建Command对象 
 SqlCommand cmd = new SqlCommand(sql, conn); 
// 创建DataReader对象 SqlDataReader dr = cmd.ExecuteReader(); 
 Console.WriteLine("============电影信息如下 ============"); // 读取数据 if(dr.Read()) 
 { 
 // 读取每列的值 
 int ID = (int)dr[0]; 
 string name = dr[1].ToString(); 
 string typeName = dr[2].ToString(); 
 string actors = dr[3].ToString(); 
 int amount = (int)dr[4]; 
 decimal price = (decimal)dr[5]; 
 string desc = dr[6].ToString(); 
 
 // 输出 
 Console.WriteLine("电影编号:{0}", ID); 
 Console.WriteLine("电影名称:{0}", name); 
 Console.WriteLine("电影类型:{0}", typeName); 
 Console.WriteLine("演员列表:{0}", actors); 
 Console.WriteLine("库存数量:{0}", amount); 
 Console.WriteLine("价格:{0}", price); 
 Console.WriteLine("描述:{0}", desc); 
 Console.WriteLine("------------------------------------"); 
 
 } // 关闭DataReader对象 
 dr.Close(); 
// 关闭连接 
 conn.Close(); 
 Console.WriteLine("\n恭喜,查询完成!"); 
 Console.ReadKey(); }

3.3、根据电影名称关键字查询电影信息

我们再来看一个例子,根据电影名称关键字进行模糊查询。模糊查询是查询功能中非常重要的一种,
具体实现的代码如下:
static void Main(string[] args) 
 { 
 Console.Write("输入要查询电影的名称:"); 
 string key = Console.ReadLine(); 
 // 连接字符串 
 string conStr = "server=.;database=FilmDB;uid=sa;pwd=123456;"; 
 
// 根据关键字查询电影的SQL语句 
 string sql = string.Format(@"select * from FilmInfo 
where Name like '{0}'","%"+key+"%");; 
 // 创建Connection对象 
 SqlConnection conn = new SqlConnection(conStr); 
 // 打开连接 
 conn.Open(); 
 // 创建Command对象 
 SqlCommand cmd = new SqlCommand(sql, conn); 
 // 创建DataReader对象 
 SqlDataReader dr = cmd.ExecuteReader(); 
 Console.WriteLine("============电影信息如下 ============"); 
 // 通过循环读取数据 
 while (dr.Read()) 
 { 
 // 读取每列的值 
 int ID = (int)dr[0]; 
 string name = dr[1].ToString(); 
 string typeName = dr[2].ToString(); 
 string actors = dr[3].ToString(); 
 int amount = (int)dr[4]; 
 decimal price = (decimal)dr[5]; 
 string desc = dr[6].ToString(); 
 // 输出 
 Console.WriteLine("电影编号:{0}", ID); 
 Console.WriteLine("电影名称:{0}", name); 
 Console.WriteLine("电影类型:{0}", typeName); 
 Console.WriteLine("演员列表:{0}", actors); 
 Console.WriteLine("库存数量:{0}", amount); 
 Console.WriteLine("价格:{0}", price); 
 Console.WriteLine("描述:{0}", desc); 
 Console.WriteLine("------------------------------------"); } 
 // 关闭DataReader对象 
 dr.Close(); 
 // 关闭连接 
 conn.Close(); 

 Console.WriteLine("\n恭喜,查询完成!"); 
 Console.ReadKey(); }
在这里,主要注意进行模糊匹配的查询 SQL 语句写法,在指定值时候要注意写上百分号%。因为查
询结果可能有多个,所以通过循环结构进行数据读取。 
 
数据库:
ADO.NET第三章:DataReader
用户验证A:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;  //引入
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("***************用户登录***************");
            Console.Write("用户名:");
            String uid = Console.ReadLine();
            Console.Write("密码:");
            String pwd = Console.ReadLine();   //输入用户名与密码
            String connStr = "server=.;uid=sa;pwd=sa;database=School;";  //连接字符串
            SqlConnection conn = new SqlConnection(connStr);  //连接对象
            String sql = String.Format("SELECT [id],[uid],[pwd],[name],[mobile] FROM [users] where uid='{0}'", uid); //将执行的SQL
            SqlCommand cmd = new SqlCommand(sql, conn);  //命令对象
            conn.Open();  //打开数据库
            SqlDataReader dr = cmd.ExecuteReader();  //执行读取
            if (dr.Read())  //下移取数据
            {
                String pwdDb = dr["pwd"].ToString();  //根据用户名获取数据库中的密码
                if (pwdDb == pwd)  //如果输入的密码与数据库中的密码一样
                {
                    Console.WriteLine("登录成功,欢迎您:"+dr["name"].ToString());  //提示登录成功
                }else
                {
                    Console.WriteLine("密码错误,请重试。");  //提示密码错误 
                }
            }else  //如果下移失败则用户不存在
            {
                Console.WriteLine("用户不存在");
            }
            dr.Close();
            conn.Close();
        }
    }
}
View Code
用户验证B:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Data.SqlClient;

namespace SchoolMIS
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("*********************学员管理系统登录*********************");
            Console.Write("用户名:");
            string uid = Console.ReadLine();
            Console.Write("密码:");
            string pwd = Console.ReadLine();
            String connStr = "server=.;database=School;uid=sa;pwd=sa;";
            SqlConnection conn = new SqlConnection(connStr);
            String sql = string.Format("select COUNT(*) from users where uid='{0}' and pwd='{1}'",uid,pwd);
            SqlCommand cmd = new SqlCommand(sql, conn);
            conn.Open();
            int count=Convert.ToInt32(cmd.ExecuteScalar());  //取单行单列的值
            conn.Close();
            if (count > 0)
            {
                Console.WriteLine("登录成功,欢迎进入本系统");
            }
            else
            {
                Console.WriteLine("验证失败,请重试");
            }

        }
    }
}
View Code
注册用户C:
 ADO.NET第三章:DataReader

 

 ADO.NET第三章:DataReader

 

 ADO.NET第三章:DataReader

五、SQL辅助工具类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Data.SqlClient;
using System.Data;

namespace DB
{
   public class SQLHelper
    {
               //只读的静态数据库连接字符串
        public static readonly string connString ="server=.;database=School;uid=sa;pwd=sa";

        #region 执行 增 删 改
        /// <summary>
        /// 执行 增 删 改
        /// </summary>
        /// <param name="sql">要执行的SQL</param>
        /// <param name="param">参数</param>
        /// <returns>影响行数</returns>
        public static int Zsg(string sql,params SqlParameter[] param)
        {
            //实例化连接对象,并指定连接字符串,自动释放资源,不用关闭
            using (SqlConnection conn = new SqlConnection(connString))
            {
                //实例化命令对象,指定sql,与连接对象
                using (SqlCommand cmd = new SqlCommand(sql, conn))
                {
                    //如果有参数
                    if (param != null)
                    {
                        //批量添加参数
                        cmd.Parameters.AddRange(param);
                    }
                    //打开连接
                    conn.Open();
                    //执行sql并返回影响行数
                    return cmd.ExecuteNonQuery();
                }
            }
        }
        #endregion

        #region 执行 查询
        /// <summary>
        /// 执行 查询
        /// </summary>
        /// <param name="sql">要执行的SQL</param>
        /// <param name="param">参数</param>
        /// <returns>数据集</returns>
        public static SqlDataReader Cx(string sql,params SqlParameter[] param)
        {
            //实例化连接对象,并指定连接字符串
            SqlConnection conn = new SqlConnection(connString);
            //实例化命令对象,指定sql,与连接对象
            using (SqlCommand cmd = new SqlCommand(sql, conn))
            {
                //如果有参数
                if (param != null)
                {
                    //批量添加参数
                    cmd.Parameters.AddRange(param);
                }
                //打开连接
                conn.Open();
                //执行sql并返回影响行数,如果将返回的SqlDataReader关闭时也将关闭连接
                return cmd.ExecuteReader(CommandBehavior.CloseConnection);
            }
        }
        #endregion

        #region 完成数据的查询,返回DataTable
        /// <summary>
        /// 表格 完成数据的查询,返回DataTable
        /// </summary>
        /// <param name="sql">要执行的sql</param>
        /// <param name="param">参数</param>
        /// <returns>DataTable</returns>
        public static DataTable Bg(string sql,params SqlParameter[] param)
        {
            //实例化连接对象,并指定连接字符串,自动释放资源,不用关闭
            using (SqlConnection conn = new SqlConnection(connString))
            {
                SqlDataAdapter adp = new SqlDataAdapter(sql, conn);
                if (param != null)
                {
                    adp.SelectCommand.Parameters.AddRange(param);
                }
                DataTable dt = new DataTable();
                adp.Fill(dt);
                return dt;
            }
        } 
        #endregion
    }
}

 增删除改示例

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication7
{
    class Program
    {
        static void Main(string[] args)
        {
            String sql = @"INSERT INTO [School].[dbo].[users]
           ([uid]
           ,[pwd]
           ,[name]
           ,[mobile])
     VALUES
           ('user007'
           ,'123567'
           ,'李小军'
           ,'18890909987')";

            //执行并返回影响行数
            int row=DB.SQLHelper.Zsg(sql);
            if(row>0)
            {
                Console.WriteLine("执行成功");
            }
            else
            {
                Console.WriteLine("执行失败");
            }
        }
    }
}

相关文章: