1.DataSet
在上两篇博客中,每次读取数据都要创建连接,执行Command得到SqlDataReader太麻烦,所以我们需要封装一个方法。
在项目中添加类,名为SQLHelper.cs,封装的方法,代码如下:
1 class SQLHepler 2 { 3 static string connStr = ConfigurationManager.ConnectionStrings["connStr"].ConnectionString; 4 public static int ExecuteNonQuery(string sql, params SqlParameter[] parameters) 5 { 6 using (SqlConnection conn = new SqlConnection(connStr)) 7 { 8 conn.Open(); 9 using (SqlCommand cmd = conn.CreateCommand()) 10 { 11 cmd.CommandText = sql; 12 foreach (SqlParameter parameter in parameters) 13 { 14 cmd.Parameters.Add(parameter); 15 } 16 return cmd.ExecuteNonQuery(); 17 } 18 } 19 } 20 public static object ExecuteScalar(string sql, params SqlParameter[] parameters) 21 { 22 using (SqlConnection conn = new SqlConnection(connStr)) 23 { 24 conn.Open(); 25 using (SqlCommand cmd = conn.CreateCommand()) 26 { 27 cmd.CommandText = sql; 28 foreach (SqlParameter parameter in parameters) 29 { 30 cmd.Parameters.Add(parameter); 31 } 32 return cmd.ExecuteScalar(); 33 } 34 } 35 } 36 public static SqlDataReader ExecuteReader(string sql, params SqlParameter[] parameters) 37 { 38 using (SqlConnection conn = new SqlConnection(connStr)) 39 { 40 conn.Open(); 41 using (SqlCommand cmd = conn.CreateCommand()) 42 { 43 cmd.CommandText = sql; 44 foreach (SqlParameter parameter in parameters) 45 { 46 cmd.Parameters.Add(parameter); 47 } 48 return cmd.ExecuteReader(); 49 } 50 } 51 } 52 public static DataTable ExecuteDataSet(string sql, params SqlParameter[] parameters) 53 { 54 using (SqlConnection conn = new SqlConnection(connStr)) 55 { 56 conn.Open(); 57 using (SqlCommand cmd = conn.CreateCommand()) 58 { 59 cmd.CommandText = sql; 60 foreach (SqlParameter parameter in parameters) 61 { 62 cmd.Parameters.Add(parameter); 63 64 } 65 DataSet dataSet = new DataSet(); 66 SqlDataAdapter adapter = new SqlDataAdapter(cmd); 67 adapter.Fill(dataSet); 68 new SqlCommandBuilder(adapter); 69 adapter.Update(dataSet); 70 return dataSet.Tables[0]; 71 } 72 } 73 } 74 }
将字符串的连接写在App.config文件中,如下:
1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <connectionStrings > 4 <add name="connStr" connectionString="Data Source=.\sqlexpress;attachDbFilename=|DataDirectory|\myDB2.mdf;Integrated Security=True;User Instance=True;"/> 5 </connectionStrings> 6 </configuration>
SqlDataReader是连接相关的,sqlDataReader中的查询结果并不是放到程序中的,而是放在数据库服务器中,SqlDataReder只是相当于放了一个指针(游标),只能读取当前游标指向的行,一旦连接断开就不能再进行读取,这样做的好处就是无论查询结果有多少条,对程序占用的内存都几乎没有影响。
SqlDataReader对于小数据量的数据来说带来的只有麻烦,优点可以忽略不计,ADO.net中提供了数据集的机制,将查询结果填充到本地内存中,这样连接断开、服务器断开都不影响数据的读取。
具体代码如下:
DataSet dataset=new DataSet();
SqlDataAdapter adapter=new SqlDataAdapter(cmd);
adapter.Fill(dataset);
SqlDataAdapter是DataSet和数据库之间沟通的桥梁、数据集DataSet包含若干表DataTable,DataTable包含若干行DataRow,
2.DataSet的更新
可以更新行row["Name"]="刘叶"、删除行datatable.Rows.Remove()、新增行datatable.NewRow(),这一切都是修改的内存中的DataSet,没有修改数据库。先写一个更新行的代码如下:
row["Name"]="刘叶";
new SqlCommandBuilder(adapter);//SqlCommandBuilder要求表必须有主键。
adapter.update(dataset);
通过DataRow的RowState可以获得行的状态(删除、修改、新增等);调用DataSet的GetChanges()方法得到变化的结果集,降低传递的资源占用。
3.省市选择的项目:
在设计中拖两个ComboBox控件,ComboBox的显示值:Items.Add的参数是Object类型,也就是可以放任意数据类型的数据,可以设置DisplayMember的属性设定显示的属性,通过SelectedItem属性去得到的就是选择的条目对应的对象。
1 private void cbProvince_SelectedIndexChanged(object sender, EventArgs e) 2 { 3 //--------------普通方法---------------------- 4 //cbCity.Items.Clear();//清除以前的数据 5 //ProvinceName item = (ProvinceName)cbProvince.SelectedItem; 6 //using (SqlConnection conn = new SqlConnection(@"Data Source=.\sqlexpress;AttachDbFilename=|DataDirectory|\myDB2.mdf;Integrated Security=True;User Instance=True;")) 7 //{ 8 // conn.Open(); 9 // using (SqlCommand cmd = conn.CreateCommand()) 10 // { 11 // cmd.CommandText = "select * from city where proID=@proID"; 12 // cmd.Parameters.Add(new SqlParameter("proID", item.Id)); 13 // using (SqlDataReader reader = cmd.ExecuteReader()) 14 // { 15 // while (reader.Read()) 16 // { 17 // string cityName = reader.GetString(reader.GetOrdinal("cityName")); 18 // cbCity.Items.Add(cityName); 19 // } 20 // } 21 22 // } 23 24 //} 25 26 //------用Dataset做的--------- 27 cbCity.Items.Clear();//清除以前的数据 28 ProvinceName item = (ProvinceName)cbProvince.SelectedItem; 29 int proID = item.Id; 30 DataTable tb = SQLHepler.ExecuteDataSet("select * from city where proID=@proID",new SqlParameter("proID",proID)); 31 for (int i = 0; i < tb.Rows.Count; i++) 32 { 33 DataRow row=tb.Rows[i]; 34 string cityname = Convert.ToString(row["cityName"]); 35 cbCity.Items.Add(cityname); 36 } 37 } 38 39 private void Form1_Load(object sender, EventArgs e) 40 { 41 42 //--------------普通方法---------------------- 43 // using (SqlConnection conn = new SqlConnection(@"Data Source=.\sqlexpress;AttachDbFilename=|DataDirectory|\myDB2.mdf;Integrated Security=True;User Instance=True;")) 44 // { 45 // conn.Open(); 46 // using (SqlCommand cmd = conn.CreateCommand()) 47 // { 48 // cmd.CommandText = "select * from promary"; 49 // using (SqlDataReader reader = cmd.ExecuteReader()) 50 // { 51 // while (reader.Read()) 52 // { 53 // ProvinceName item = new ProvinceName(); 54 // item.Id = reader.GetInt32(reader.GetOrdinal("proID")); 55 // item.Name = reader.GetString(reader.GetOrdinal("proName")); 56 // cbProvince.Items.Add(item); 57 // } 58 59 // } 60 61 // } 62 // } 63 64 //------用Dataset做的--------- 65 ProvinceName item = new ProvinceName(); 66 DataTable tb = SQLHepler.ExecuteDataSet("select * from promary"); 67 for (int i = 0; i < tb.Rows.Count; i++) 68 { 69 item.Id=Convert.ToInt32( tb.Rows[i]["proID"]); 70 item.Name=Convert.ToString( tb.Rows[i]["proName"]); 71 cbProvince.Items.Add(item); 72 } 73 74 } 75 76 } 77 class ProvinceName 78 { 79 public int Id { get; set; } 80 public string Name { get; set; } 81 }
4.手机归属地查询的程序
1 namespace 手机号码归属地查询 2 { 3 public partial class Form1 : Form 4 { 5 public Form1() 6 { 7 InitializeComponent(); 8 } 9 10 private void btnImport_Click(object sender, EventArgs e) 11 { 12 FolderBrowserDialog fbDialog = new FolderBrowserDialog(); 13 if (fbDialog.ShowDialog() != DialogResult.OK) 14 { 15 return; 16 } 17 string path = fbDialog.SelectedPath;//选取用户选择的路径 18 string[] strs = Directory.GetFiles(path, "*.txt", SearchOption.TopDirectoryOnly);//获得用户选择文件下的所有*.txt文件 19 string connStr=ConfigurationManager.ConnectionStrings["connStr"].ConnectionString; 20 using (SqlConnection conn = new SqlConnection(connStr)) 21 { 22 conn.Open(); 23 using (SqlCommand cmd1 = conn.CreateCommand()) 24 { 25 //清除旧数据 26 cmd1.CommandText = "delete from T_Phone"; 27 cmd1.ExecuteNonQuery(); 28 } 29 using (SqlCommand cmd = conn.CreateCommand()) 30 { 31 cmd.CommandText = "insert into T_Phone values(@startNo,@endNo,@cityName)"; 32 foreach (string str in strs) 33 { 34 string proName = Path.GetFileNameWithoutExtension(str);//获得每个txt文件的没有后缀文件名 35 string[] lines = File.ReadAllLines(str, Encoding.Default); 36 foreach (string line in lines) 37 { 38 string[] data = line.Split('-');//以“—”进行分割取出数据 39 string startNo = data[0]; 40 string endNo = data[1]; 41 string cityName = proName + data[2]; 42 cmd.Parameters.Clear(); 43 cmd.Parameters.Add(new SqlParameter("startNo",startNo)); 44 cmd.Parameters.Add(new SqlParameter("endNo",endNo)); 45 cmd.Parameters.Add(new SqlParameter("cityName",cityName)); 46 cmd.ExecuteNonQuery(); 47 } 48 49 } 50 51 } 52 } 53 MessageBox.Show("导入成功!"); 54 55 56 } 57 58 private void button1_Click(object sender, EventArgs e) 59 { 60 long number =Convert.ToInt64( textBox1.Text); 61 string connStr=ConfigurationManager.ConnectionStrings["connStr"].ConnectionString; 62 using (SqlConnection conn = new SqlConnection(connStr)) 63 { 64 conn.Open(); 65 using (SqlCommand cmd = conn.CreateCommand()) 66 { 67 cmd.CommandText = "select * from T_phone"; 68 using (SqlDataReader reader = cmd.ExecuteReader()) 69 { 70 while (reader.Read()) 71 { 72 string startNo = reader.GetString(reader.GetOrdinal("startNo")); 73 string endNo = reader.GetString(reader.GetOrdinal("endNo")); 74 string cityName = reader.GetString(reader.GetOrdinal("cityName")); 75 if (number >=Convert.ToInt64( startNo) && number <=Convert.ToInt64( endNo)) 76 { 77 MessageBox.Show(cityName); 78 } 79 } 80 } 81 } 82 83 } 84 } 85 } 86 }
5.可空数据类型
C#中值类型(int、Guid、bool等)是不可以为空的,int i=null;是错误的,因此int、bool等这些类型不能表示数据库中的“Null”。因此C#提供了“可空类型”这种语法,只要在类型后加?就构成了可空的数据类型,比如int?、bool? ,这样int? i=null就可以了。这是为了解决数据库中的int可以为null,而C#中int不能为null的问题。
判断可空数据是否为空,i==null或者i.HasValue;得到可空变量的值,int i1=(int)i或者int i1=i.Value.
类型转换:不可空类型赋值给可空数据类型无需显示转换(一定成功),可控数据类型赋值给不可空类型则需要显示转换(不一定成功)。