1¥ 查询数据

1$ 认识DataReader对象
     使用DataReader对象可以从数据库中检索只读的数据,每次从查询结果中读取一行到内存,所以使用DateReader操作非常快。

1.。.NET数据库提供程序及其DataReader类
  SqlDataReader    SQL数据库提供程序
                  使用System.Data.SqlClient命名空间

  。。。。。。其他的数据库中的DataReader暂略,详见p173,表7-1

特别注意:用DataReader读取数据时,不能对数据进行修改,所以它
          是只读的。
         而且,在读取数据的时候要保持与数据库的连接。

2.。DataReader对象的主要属性和方法
 属性: HasRows     是否返回了结果,有结果返回True
                                     无结果返回False

        FieldCount    当前行中的列数

 方法: Read()     前进到下一行记录,如果读到记录返回True
                        下一行如果无记录,返回False

        Close()    关闭DataReader对象

2$ 如何使用DataReader对象
    创建一个DataReader对象,需要调用Command对象的ExecuteReader()方法。返回值就是一个DataReader对象。
    然后就可以调用DataReader对象的Read()方法来读取一行记录。

    具体步骤:

特别注意:应办好using System.Data.SqlClient;的包含

1.。定义一条查询字符串
 string sql = “select gradename from grade”;

2.。定义Command对象
SqlCommand command = new SqlCommand(sql,
                                 DBHelpper.connection);

3.。打开数据库连接
  DBHelpper.connection.Open();

4.。调用Command对象的ExecuteReader()方法创建DataReader
    对象
    SqlDataReader dataReader = command.ExecuteReader();

5.。使用DataReader的Read()方法逐行读取数据
    Read()方法返回一个布尔值,有数据返回True,否则返回False。

    dataReader .Read();

6.。读取当前行的某列数据
    用方括号来读取某列的值,如(type)dataReader[]。
    像数组一样使用列的索引,从0开始,也可以使用列名。
    取出的列值必须要进行类型转换。

    (string)dataReader[0]

7.。关闭DataReader()方法,调用它的Close()方法
    使用DataReader读取数据的时候会占用数据库连接,必须调用它
    的Close方法关闭DataReader,便于用connection进行其他连接。

    dataReader . Close();

2¥ 操作数据
    对数据库进行增删改,需使用Command对象的ExecuteNonQuery()方法。

    ExecuteNonQuery()方法用于执行指定的SQL语句,如:update、insert、
    delete,其返回值是受SQL语句影响的行数

    具体步骤:

1$ 创建Connection对象(在DBHelpper类中已创建好)

2$ 定义要执行的SQL语句
   string sql = string.Fromat(“……”);

3$ 创建Command对象
   SqlCommand command = new SqlCommand(sql, DBHelpper.connection);

4$ 执行ExecuteNonQuery()方法
   int result = command.ExecuteNonQuery();
   //返回执行语句后受到影响的行数

5$ 根据返回值的结果进行后续的处理
   如果返回值小于或等于0,说明没有记录受影响。即查询语句执行失败。

3¥ 控件进阶

1$ ListView(视图列表)控件
    以特定样式或视图类型显示列表项,可以创建象Windows资源管理器右侧窗格一样的界面。

   ListView控件的主要属性:
           Columns                视图中显示的列
           FullRowSelect           当选中一项时,它的子项是否同该
                                  项一起突出显示
           Items                   ListView中所有项的集合
           MultiSelect              是否允许选择多项
           SelectedItems            选中的项的集合
           View                   指定显示5种视图中的那一种
                                  listview中必须设置成Detail
                                 
           GridLine(t/f)             显示网格线

   ListView控件的主要事件:
           MouseDoubleClick        鼠标双击事件

   ListView控件的主要方法:
           Clear( )                 移除ListView中的所有项

特别注意:ListView控件列表视图的Items属性,它的每一项都是一个列
          表项(ListViewItem),可以使用Items.Add( )方法向列表视图
          中添加项。

特别注意:实现ListView显示查询结果的具体步骤

1)ListView显示查询结果的实质,是将DataReader对象使用Read()
  方法查询到的结果,中的每一行显示在ListView中。

  通常修改ListView的View属性,为Detail(详细信息模式,分列)

2)而ListView中数据,是按照每个ListViewItem对象占一行组织的

3)每一个ListView对象又是一个String[]型的数组,数组显示名为
   首项名,即首列名
3)所以,应先定义若干字符串变量,存储Read()查询结果中的
   每一列的值

   如:   string Question;
            string OptionA;
            string OptionB;
            string OptionC;
            string OptionD;
            string Answer;
            string Difficulty;
4)然后就可以定义查询语句了

string sql = string.Format("select QuestionId,Question,OptionA,OptionB,OptionC,OptionD,Answer,Difficulty from Question where Difficulty='{0}'", cmbDiffLevel.SelectedItem);
5)然后,有几步很俗的,但也得做
 SqlCommand cd = new SqlCommand(sql, DBHelpper.connection);
 DBHelpper.connection.Open();
 SqlDataReader c = cd.ExecuteReader();
6)清空ListView中的原有数据
   lvQuetionSearch.Items.Clear();
7)判断DataReader对象是否读到了结果
    if (!c.HasRows)
8)如果有结果则用Read()方法循环增加ListView中的项

while (c.Read())  //效果是每循环一次,增加一个ListView对象行

{

     Question = (string)c["Question"];

     OptionA = (string)c["OptionA"];

     OptionB = (string)c["OptionB"];

     OptionC = (string)c["OptionC"];

     OptionD = (string)c["OptionD"];

     Answer = (string)c["Answer"];

     Difficulty =c["Difficulty"].ToString();

 

 ListViewItem aaa = new ListViewItem(Question);
 //定义一个新的ListViewItem对象,首项列名显示为问题名Question

 

 aaa.Tag = (int)c["QuestionId"];  //将主键Id放在Tag中

 

 lvQuetionSearch.Items.Add(aaa);
//向ListView控件中添加刚刚创建好的ListView对象

 

aaa.SubItems.AddRange(new string[] { OptionA, OptionB, OptionC, OptionD, Answer, Difficulty });

 

   }
}

9)详解While循环中的重点
1。。为所有的待用字符串赋给查询结果中相应的列值(要转换类型)
2。。创建局部ListViewItem类型的对象变量

    ListViewItem aaa = new ListViewItem(Question);
     //定义一个新的ListViewItem对象,首项列名显示为问题名Question

3。。向ListView中添加刚刚建好的ListView对象(Add()方法)
    lvQuetionSearch.Items.Add(aaa);
     //向ListView控件中添加刚刚创建好的ListView对象

4。。使用AddRange()方法,给刚添加的ListView对象添加子项,
    即将赋好值的字符串写入ListViewItem对象的string[]数组中

    aaa.SubItems.AddRange(new string[] { OptionA, OptionB, OptionC,
     OptionD, Answer, Difficulty });
10)关闭DataReader对象
    c.Close();


  

2$ ContextMenuStrip(快捷菜单)控件
   快捷菜单也可以叫做上下文(Context)菜单,俗称右键菜单。
   许多控件都有ContextMenuStrip属性,通过它可以指定与本控件相关
   的右键快捷菜单。

2$.1向窗体中增加(ContextMenuStrip)右键快捷菜单的基本步骤
 1。。双击控件箱中的ContextMenuStrip控件,为窗体增加
 2。。在ContextMenuStrip中输入控件选项文本,如:删除,更新等
 3。。在窗体的ContextStrip属性中选择刚刚增加的ContextStrip控件
      名,使之关联。

     通常将窗体显示控件中的选择属性设置为整行选取:

     ListView中:    FullRowSelect=True;
     DataGridView中:SelectionMode=FullRowSelect;

 4。。给ContextMenuStrip控件的选项按钮编写单击事件程序
     即:写代码




1.。把快捷菜单和某个控件相关联
    0)先将快捷菜单控件拖到窗口上,窗口下方将显示其名字
    1)选中文本框
    2)在属性窗口中找到它的ContextMenuStrip属性
    3)选择已经有的(刚托来的)右键菜单控件就行了。

2.。快捷菜单中的菜单项(MenuItem)都有自己的属性和事件

    属性: Display Style   指定是否显示图像和文本
           Image         显示在菜单项上的图像
           Text           显示在菜单项上的文本

    事件: Click          单击事件

特别注意:(代码详见P185示例4)
    为了向ListView中添加结果,应先创建一个列表视图项(ListViewItem),显示名为loginId。然后用Items.Add()方法将这个列表视图项添加到列表视图中。

    调用列表视图项的SubItem.AddRange()方法添加子菜单项(SubItems),这个方法接受的是一个字符串数组。

    为了唯一标识结果,把Student表主键StudentId也取出,放在了视图列表项的Tag属性中。

    Tag是标签的意思,很多控件都有这个属性,可以存放一个对程序有用,但又不需要用户看到的值。

特别注意:(代码详见P185示例5)
    使用列表视图的SelectItems.Count属性,判断列表视图选中的项的数量。如果值为0,说明没有选择任何用户。

    首先通过SelectItems[0].Tag读出要修改的这条记录对应的Student

    ExcuteNonQuery()方法返回受影响的行数,如果结果不等于1,说明没有记录受到影响,修改不成功。

4¥ 操作数据库小结

1$ 查询单个值
   using System.Data.SqlClient;
   使用Command对象的ExcuteScalar()方法,步骤:
   1)创建Connection对象(数据库连接对象)
   2)创建查询用的SQL语句
   3)利用SQL语句和Connetion对象创建Command对象
   4)打开数据库连接,调用Connection对象的Open()方法
   5)调用Command对象的ExecuteScalar()方法,返回一个标量值
   6)操作完成后关闭数据库连接,调用Connetion对象的Close()方法

2$ 查询若干条记录
   using System.Data.SqlClient;
  使用Command对象的ExecuteReader()方法,步骤:
   1)创建Connetion对象(数据库连接对象)
   2)创建查询用的SQL语句
   3)利用SQL语句和Connetion对象创建Command对象
   4)打开数据库连接,调用Connection对象的Open()方法
   5)调用Command对象的ExecuteReader()方法,返回一个DataReader
      对象(这个DataReader对象包含了查询结果的所有行)
   6)调用DataReader对象的Read()方法逐行读取结果中的记录,如果读
      到就返回True,否者返回false。(一般用循环控制)
   7)使用(type)dataReader[列名或索引]的方式读取这一行中的某一列
      (type)为强制类型转换
   8)关闭DataReader对象
   9)操作完成后关闭数据库连接,调用Connetion对象的Close()方法

3$ 非查询操作
   using System.Data.SqlClient;
  使用ExecuteNonQuery()方法,步骤:
   1)创建Connetion对象(数据库连接对象)
   2)创建查询用的SQL语句
   3)利用SQL语句和Connetion对象创建Command对象
   4)打开数据库连接,调用Connection对象的Open()方法
   5)调用Command对象的ExecuteNonQuery方法执行命令,返回受影
      响的行数。
   6)操作完成后关闭数据库连接,调用Connetion对象的Close()方法