第四天 -- 《2014-07-09 ADO》 -- DataReader多结果集的读取、参数化查询、ComboBox下拉列表的数据绑定

一、上午《01、数据库操作流程》--《06、NextResult》

1、杂项

<1>每个Winform控件有一个ContextMenuStrip属性,可以为它指定已创建的右键菜单。

<2>数据库中的数值,被DataReader读取过来后已经被装箱。而我们需要将数据拆箱,注意拆箱操作只能拆到原始的数据类型。(比如把int装箱object,后者只能拆箱为int。假如希望转换为double,那必须(double)(int)obj,即拆箱完再转换。)

 

2、读取多个结果集时,使用DataReader.NextResult

  SqlCommand命令的sql语句可以是多条语句。例如“select * from grade; select * from student;”这样服务器会返回两个结果集。我们用DataReader读取完第一个结果集后,可以使用NextResult判断是否存在下一个结果集,如果存在,读取器会自动指向下一个结果集开始位置,然后我们再通过Read()方法去读取。如:

 1 ...
 2 
 3 conn.Open();
 4 string sql = "select subjectid,subjectname,classhour,classid from subject; select stuname from student";
 5 SqlCommand comm = new SqlCommand(sql,conn);
 6 //创建这个对象,相当于向服务器请求数据,服务器会将响应,将数据存储到服务器的缓存中。你还需要通过某种方式去服务器缓存中读取出数据
 7 SqlDataReader reader = comm.ExecuteReader();
 8 while (reader.Read())
 9 {//Read():判断有没有下一行记录,如果有就将读取指针移动到下一行记录,同时将这一行记录的数据读取到reader对象的_data数组。数组是一私有数组,通过方法或者索引器进行访问
10 
11     if (! (reader["classid"] is DBNull))
12     {//数据库中的null读取到c#后就被封装为DBNull类型
13         int cid = Convert.ToInt32(reader["classid"]);
14     }
15     
16     //先创建主项,再为主项添加子项
17     ListViewItem lv = new ListViewItem(reader.GetInt32(0).ToString());
18     lv.SubItems.AddRange(new string[]{reader["subjectname"].ToString(),reader["classhour"].ToString(),reader["classid"].ToString()});
19     this.lvSubejct.Items.Add(lv);
20 }
21 if(reader.NextResult())
22 {//判断有没有下一个结果集,如果有就将读取指针移动到下一个结果集
23     while(reader.Read())
24     {
25         ListViewItem lv = new ListViewItem(reader[0].ToString());
26         lv.SubItems.Add(reader[1].ToString());
27         this.listView1.Items.Add(lv);
28     }
29 }
30 
31 ...

 

 

 

二、上午《07、数据库中的null读取到c#后就被封装为DBNull类型》

1、C#中的null与数据库中的null根本是两个概念

  C#中的null表示空引用。引用类型变量为null表示不指向(不引用)堆上的任何对象实例。而数据库中的null表示未知数据(即该数据未录入),数据库中根本就没有引用类型这种概念。

  当数据库的null被DataReader读取后,会创建一个System.DBNull类型的对象来表示它。因为DataReader读取的数据都为object类型,我们在做数据转换的时候,需要用DataReader.IsDBNull()来判断是否是DBNull(当然也可以用if (xxx is DBNull) 来判断)。是DBNull的话不可以强制转换,否则会报转换失败的异常(DBNull转成其他数值都抛异常,转字符串得到String.Empty对象,即空字符串)。

 

 

三、上午《08、参数化查询》

1、sql字符串注入漏洞(sql拼接的漏洞)

举一个sql注入漏洞的小例子:

 

2、ADO.NET的参数化查询解决上面的漏洞

<1>sql语句要使用参数化查询语句

<2>为SQLCommand添加SqlParamter

 1 //1.定义参数占位 @参数 相当于在sql中创建一个变量,所以也不需要使用'  '引号包含
 2 string sql = "select count(*) from [user] where username=@name and pwd=@pwd";
 3 //2.在c#中创建对应的 参数对象.参数名称不区分大小写.第一个参数是指对应的形参名称,第二个参数是指你需要赋的值
 4 SqlParameter p = new SqlParameter("@name", txtName.Text.Trim());
 5 SqlParameter p2=new SqlParameter("@pwd", txtPwd.Text.Trim());
 6 
 7 SqlCommand comm = new SqlCommand(sql, conn);
 8 //3.还需要将创建好的参数传递的服务器让其使用。所以让comm对象将参数一起传递过去 
 9 comm.Parameters.Add(p);
10 comm.Parameters.Add(p2);
11 
12 int num = (int)comm.ExecuteScalar();//执行命令,获取Count计数
13 
14 if (num > 0)
15 {
16     MessageBox.Show("登录ok");
17 }
18 else
19 {
20     MessageBox.Show("登录失败");
21 }

 

 

四、下午《01、数据的导入和导出》--《02、如何插入数据库null》

1、参数化查询,将数据库null插入记录,如下例子(代码片段):

 1 string sql = "insert into [user] values(@username,@pass,@email,@phone)";
 2 SqlParameter[] ps = 
 3     { 
 4         new SqlParameter("username",txtName.Text.Trim()),
 5         new SqlParameter("pass",txtPwd.Text.Trim()),
 6         new SqlParameter("email",string.IsNullOrEmpty(txtEmail.Text.Trim())? DBNull.Value:(object)txtEmail.Text.Trim()),
 7         new SqlParameter("phone",string.IsNullOrEmpty(txtPhone.Text.Trim())? DBNull.Value:(object)txtPhone.Text.Trim())
 8     };
 9 SqlCommand comm = new SqlCommand(sql, conn);
10 comm.Parameters.AddRange(ps);
11 int num = comm.ExecuteNonQuery();

注意:在本例代码第6、7行创建SqlParameter时,要提供一个object类型的对象。虽然C#中所有类型都继承自object类型,但DBNull.Value是DBNull类型(DBNull继承自object),txtEmail.Text.Trim()返回的是String类(String继承自object)对象。三元操作符 ?: 要求冒号两边对象的类型能够隐式转换,显然DBNull与String不能隐式转换。所以需要先将后者强制转到object,这样就和DBNull有了隐式转换关系(即DBNull可以隐式转换到object)。

 

 

五、下午《03、初步实现省市级联》--《04、使用实体类对象做为下拉列表的项》

1、Winform的ComboBox添加实体类对象时,指定显示的属性值

 1 class Student
 2 {
 3      public int Id{get;set;}
 4      public string Name{get;set;}
 5      public int Age{get;set;}
 6 }
 7 
 8 
 9 ...
10 Student stu = new Student { Id = 1, Name = "小明", Age = 10 };
11 cbx_Student.DisplayMember = "Name";//指定下拉列表显示对象的Name属性值,注意"Name"可以不区分大小写。
12 cbx_Student.Items.Add(stu);
13 ...
14 
15 
16 private void cbx_Student_SelectedIndexChanged(object sender, EventArgs e)
17 {
18     int id = (cbx_Student.SelectedItem as Student).Id;//因为ComboBox的每个项都是Student对象。所以可以在这里转换过来
19     txt_Id.Text = id.ToString();
20 }

 

2、Winform的ComboBox可以直接绑定实体类对象的集合(即指定ComboBox.DataSource属性)

 1 ...
 2 List<Student> list = new List<Student>();
 3 for (int i = 0; i<10; i++)
 4 {
 5     Student stu = new Student { Id = 1 + i, Name = "小明" + i, Age = 10 };
 6     list.Add(stu);//为列表添加若干实体对象
 7 }
 8 cbx_Student.ValueMember = "Id";//下拉列表项被选中后,选中的值是对象的哪个属性的值。
 9 cbx_Student.DisplayMember = "Name";//下拉列表显示的对象属性
10 cbx_Student.DataSource = list;//指定数据源。注意要先指定上面两个属性,再绑定数据源
11 ...
12 
13 
14 private void cbx_Student_SelectedIndexChanged(object sender, EventArgs e)
15 {
16     int id = (int)cbx_Student.SelectedValue;//选中值实际上就是实体对象的Id值
17     txt_Id.Text = id.ToString();
18 }

 

posted on 2017-08-13 20:48  困兽斗  阅读(260)  评论(0)    收藏  举报

导航