1、ADO.NET基礎介紹
(1、程序要和數據庫交互要通過ADO.NET進行,通過ADO.NET就能在程序中執行SQL了。ADO.Net中提供了對各種不同數據庫的統一操作接口。
(2、直接在項目中內嵌mdf文件的方式使用SQL Server數據庫(基於服務的數據庫)。mdf文件隨着項目走,用起來方便,和在數據庫服務器上創建數據庫沒什么區別,運行的時候會自動附加(Attach)。
(3、雙擊mdf文件會在“服務器資源管理器”中打開,管理方式和在Mnagemen Studio沒什么本質不同,要拷貝mdf 文件需要關閉所有指向mdf文件的連接。
(4、正式生產運行的時候附加到SQLServer上、修改連接字符串即可,除此之外沒有任何的區別,在“數據庫”節點上點右鍵“附加”;在數據庫節點上à任何à分離 就可以得到可以拷來拷去mdf 文件。
(5、用的時候要在控制台、WinForm項目中的Main函數最開始的位置加入“一段神奇的代碼"。ASP.Net項目中不需要。

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Data.SqlClient; 6 7 namespace myadonet 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //神奇代碼 14 string dateDir = AppDomain.CurrentDomain.BaseDirectory; 15 if (dateDir.EndsWith(@"\bin\Debug\") 16 || dateDir.EndsWith(@"\bin\Release\")) 17 { 18 dateDir = System.IO.Directory.GetParent(dateDir).Parent.Parent.FullName; 19 AppDomain.CurrentDomain.SetData("DataDirectory", dateDir); 20 } 21 22 using (SqlConnection conn = new SqlConnection(@"Data Source=.\SQLEXPRESS;AttachDBFilename=|DataDirectory|\Database1.mdf;Integrated Security=True;User Instance=True")) 23 { 24 conn.Open(); 25 26 Console.WriteLine("連接成功!"); 27 Console.ReadKey(); 28 } 29 } 30 }
2、連接到SQLServer數據庫
(1、連接字符串:程序通過連接字符串 指定要連哪台服務器上的、哪個實例的哪個數據庫、用什么用戶名 密碼等。
(2、項目內嵌mdf文件形式的連接字符串“Data Source=.\SQLEXPRESS;AttachDBFilename=|DataDirectory|\Database1.mdf;Inte grated Security=True;User Intance=True”。“.SQLEXPRESS”表示本機上的SQLEXPRESS實例,如果數據庫實例名不是SQLEXPRESS,則需要修改。 “Database1.mdf”為mdf的文件名。
(3、ADO.Net中通過SQLConnection在創建SQLServer的連接,SQLConnection代表一個數據庫連接,ADO.Net中的連接等資源都實現了IDisposable接口,可以使用using進行資源管理。執行這段段代碼,如果成功了就OK。
(4、在實現了IDisposable接口的對象,在使用完后需要用行資源釋放。
3、執行簡單的Insert語句
(1、SQLCommand表示向服務器提交的一個命令(SQL語句等)。
(2、CommandText屬性為要執行的SQL語句,Execute NonQuery方法執行一個非查詢語句(Update、inset、Delete等)
(3、ExecuteNonQuery返回值是執行的影響行數
在conn.open();下面敲上這樣一段代碼即可插入數據庫數據:

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Data.SqlClient; 6 7 namespace myadonet 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 //神奇代碼 14 string dateDir = AppDomain.CurrentDomain.BaseDirectory; 15 if (dateDir.EndsWith(@"\bin\Debug\") 16 || dateDir.EndsWith(@"\bin\Release\")) 17 { 18 dateDir = System.IO.Directory.GetParent(dateDir).Parent.Parent.FullName; 19 AppDomain.CurrentDomain.SetData("DataDirectory", dateDir); 20 } 21 22 using (SqlConnection conn = new SqlConnection(@"Data Source=.\SQLEXPRESS;AttachDBFilename=|DataDirectory|\Database1.mdf;Integrated Security=True;User Instance=True")) 23 { 24 conn.Open(); 25 /* 插入數據* */ 26 using (SqlCommand commd = conn.CreateCommand()) { 27 commd.CommandText = "Insert into T_UserInfo (sUser,sPassWord) values('admin','888888')"; 28 commd.ExecuteNonQuery(); 29 Console.WriteLine("插入成功"); 30 } 31 32 33 } 34 35 Console.WriteLine("連接成功!"); 36 Console.ReadKey(); 37 } 38 } 39 }
4、模擬登陸
同樣在conn.open();下面敲上這樣一段代碼即可

1 bool flag = true; 2 while (flag) 3 { 4 Console.WriteLine("請輸入用戶名:"); 5 string sUser = Console.ReadLine(); 6 using(SqlCommand cmd=conn.CreateCommand()){ 7 cmd.CommandText = "Select * from T_UserInfo where sUser='"+sUser+"'"; 8 using (SqlDataReader reader = cmd.ExecuteReader()) { 9 if (reader.Read()) 10 { 11 Console.WriteLine("請輸入密碼:"); 12 string sPassWord = Console.ReadLine(); 13 string QueryPassWord=reader.GetString(reader.GetOrdinal("sPassWord")); 14 if (sPassWord == QueryPassWord) 15 { 16 Console.WriteLine("登陸成功!"); 17 flag = false; 18 } 19 else { 20 Console.WriteLine("密碼錯誤"); 21 } 22 } 23 else { Console.WriteLine("用戶不存在,請重新輸入"); } 24 } 25 } 26 }
5、ExecuteScalar
(1、SqlCommand中的ExecuteScalar方法用於執行查詢,並返回查詢所返回的結果集中第一行的第一列,因為不能確定返回值的類型,所以,ExecuteScalar的返回值為object類型。
(2、得到自動增長字段的主鍵值,在values關鍵詞前加上output inserted.Id,其中Id為主鍵字段名。執行結果就是插入的主鍵值,用ExecuteScalar執行最方便。

1 using (SqlCommand cmd = conn.CreateCommand()) 2 { 3 cmd.CommandText = "Select * from T_UserInfo"; 4 using (SqlDataReader reader = cmd.ExecuteReader()) 5 { 6 while (reader.Read()) //這里得到一個bool值 7 { 8 string sUser = reader.GetString(reader.GetOrdinal("sUser")); 9 //int ID = reader.GetInt32(reader.GetOrdinal("ID")); 10 string sPassWord = reader.GetString(reader.GetOrdinal("sPassword")); //多行結果集 11 Console.WriteLine("{0}{1}", sUser, sPassWord); 12 13 } 14 } 15 }
(3、執行有多行結果集的用 ExecuteReader:讀到最后一條數據返回false
reader的GetString、GetInt32等方法只接受整數參數,也就是序號,用GetOrdinal方法根據列名動態得到序號了。

1 /*最佳登陸方式*/ 2 bool flag = true; 3 while (flag) 4 { 5 Console.WriteLine("請輸入用戶名:"); 6 string sUser = Console.ReadLine(); 7 using (SqlCommand cmd = conn.CreateCommand()) 8 { 9 cmd.CommandText = "Select * from T_UserInfo where sUser='" + sUser + "'"; 10 using (SqlDataReader reader = cmd.ExecuteReader()) 11 { 12 if (reader.Read()) 13 { 14 Console.WriteLine("請輸入密碼:"); 15 string sPassWord = Console.ReadLine(); 16 string QueryPassWord = reader.GetString(reader.GetOrdinal("sPassWord")); 17 if (sPassWord == QueryPassWord) 18 { 19 Console.WriteLine("登陸成功!"); 20 flag = false; 21 } 22 else 23 { 24 Console.WriteLine("密碼錯誤"); 25 } 26 } 27 else { Console.WriteLine("用戶不存在,請重新輸入"); } 28 } 29 } 30 }
6、為什么用using?
Close:關閉以后還能打開。 Dispose:直接銷毀,不能再次使用。
Using在出了作用域以后調用Dispose,SqlConnection 、FileStream 等的Dispose內部都會做這樣的判斷:判斷有沒有close,如果沒有,就
先Close再Dispose。
7、SQL注入漏洞攻擊/參數化查詢
**例如第4點所說的登錄判斷:select count(*) from T_Users where sUser=…and Password=…,將參數拼到SQL語句中。
我們可以通過構造惡意的sPassword輸入 1`or`1`=`1
編譯通過后識別出來的就是:select count(*) from T_Users where sUser= ‘admin’ and Password=‘1`or`1`=`1’
**參數化查詢解決漏洞攻擊
SQL語句使用@sUser表示“此處用參數代替”,向SqlCommand的Parameters中添加參數。

1 cmd.CommandText = "select count(*)from T_Users where sUser =@UN and sPassword=@PW"; 2 3 cmd.Parameters.Add(new SqlParameter("UN", sUser)); 4 5 cmd.Parameters.Add(new SqlParameter("PW", sPassword));
參數在SQLServer內部不是簡單的字符串替換,SQLServer直接用添加的值進行數據比較,因此不會有注入漏洞攻擊。
8、模擬窗體登陸,並且設置登陸錯誤次數

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.Data.SqlClient; 10 11 namespace myAdoNet02 12 { 13 public partial class Form1 : Form 14 { 15 public Form1() 16 { 17 InitializeComponent(); 18 } 19 20 private void IntsErrorTime() 21 { 22 using (SqlConnection conn = new SqlConnection(@"Data Source=.\SQLEXPRESS;AttachDBFilename=|DataDirectory|\Database1.mdf; 23 Integrated Security=True;Connect Timeout=30;User Instance=True")) 24 { 25 conn.Open(); 26 using (SqlCommand cmd = conn.CreateCommand()) 27 { 28 using (SqlCommand updateCmd = conn.CreateCommand()) 29 { 30 //假如用戶輸入的用戶名和密碼錯誤次數過多,則將數據庫中的錯誤記錄次數加1 31 updateCmd.CommandText = "update T_UserInfo Set sErrorTime=sErrorTime+1 where sUser=@sUser"; 32 updateCmd.Parameters.Add(new SqlParameter("sUser", textBox1.Text)); 33 updateCmd.ExecuteNonQuery(); 34 } 35 } 36 } 37 } 38 private void ResetsErrorTime() 39 { 40 using (SqlConnection conn = new SqlConnection(@"Data Source=.\SQLEXPRESS;AttachDBFilename=|DataDirectory|\UsersDB.mdf; 41 Integrated Security=True;Connect Timeout=30;User Instance=True")) 42 { 43 conn.Open(); 44 using (SqlCommand cmd = conn.CreateCommand()) 45 { 46 using (SqlCommand updateCmd = conn.CreateCommand()) 47 { 48 //假如用戶輸入的用戶名和密碼均正確,則將數據庫的錯誤次數歸0,重新統計。 49 updateCmd.CommandText = "update T_UserInfo Set sErrorTime=0 where sUser=@sUser"; 50 updateCmd.Parameters.Add(new SqlParameter("sUser", textBox1.Text)); 51 updateCmd.ExecuteNonQuery(); 52 } 53 } 54 } 55 } 56 private void button1_Click(object sender, EventArgs e) 57 { 58 using (SqlConnection conn = new SqlConnection(@"Data Source=.\SQLEXPRESS;AttachDBFilename=|DataDirectory|\UsersDB.mdf; 59 Integrated Security=True;Connect Timeout=30;User Instance=True")) 60 { 61 conn.Open(); 62 using (SqlCommand cmd = conn.CreateCommand()) 63 { 64 cmd.CommandText = "Select * from T_UserInfo where sUser=@sUser";//加"@"參數化查詢 65 cmd.Parameters.Add(new SqlParameter("sUser", textBox1.Text)); 66 using (SqlDataReader reader = cmd.ExecuteReader()) 67 { 68 if (reader.Read()) 69 { 70 int errorTimes = reader.GetInt32(reader.GetOrdinal("sErrorTime")); 71 if (errorTimes > 3) 72 { 73 MessageBox.Show("錯誤次數過多,請三小時后再登錄"); 74 return; 75 } 76 string dbpassword = reader.GetString(reader.GetOrdinal("Password")); 77 if (dbpassword == textBox2.Text) 78 { 79 ResetsErrorTime(); 80 MessageBox.Show("登錄成功!"); 81 } 82 else 83 { 84 //在同一個連接中,如果SqlDataReader沒有關閉,那么是不能執行Update之類的語句的, 85 //因此,Update語句要放在其它函數內。 86 IntsErrorTime();//調用此方法即可 87 MessageBox.Show("登錄失敗!"); 88 } 89 } 90 else 91 { 92 MessageBox.Show("用戶名不存在!"); 93 } 94 } 95 } 96 } 97 } 98 } 99 }
9、導入導出數據案例

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.IO; 10 using System.Data.SqlClient; 11 12 namespace myAdoNet02 13 { 14 public partial class Form2 : Form 15 { 16 public Form2() 17 { 18 InitializeComponent(); 19 } 20 21 private void button1_Click(object sender, EventArgs e) 22 { 23 //單純從button中的name屬性objImport得到ShowDialog()方法是不科學的 24 // 25 OpenFileDialog objImport = new OpenFileDialog(); 26 if (objImport.ShowDialog() != DialogResult.OK) 27 { 28 return; 29 } 30 using (FileStream filestream = File.OpenRead(objImport.FileName)) 31 { 32 using (StreamReader streamreader = new StreamReader(filestream)) 33 { 34 using (SqlConnection conn = new SqlConnection(@"Data Source=.\SQLEXPRESS;AttachDBFilename=|DataDirectory|\Database1.mdf; 35 Integrated Security=True;Connect Timeout=30;User Instance=True")) 36 { 37 //創建連接是很耗時的,所以不能每插入一條數據就創建一次連接 38 conn.Open(); 39 using (SqlCommand cmd = conn.CreateCommand()) 40 { 41 cmd.CommandText = "insert into T_UserInfo(sUser,sPassWord) values(@sUser,@sPassWord)"; 42 string line = null; 43 while ((line = streamreader.ReadLine()) != null) 44 { 45 string[] str = line.Split('|'); 46 string sUser = str[0]; 47 string sPassWord = str[1]; 48 cmd.Parameters.Clear(); 49 //參數不能重復添加,在本while中用的是同一個SqlCommand對象,所以要在用完一次后,清除參數 50 cmd.Parameters.Add(new SqlParameter("sUser", sUser)); 51 cmd.Parameters.Add(new SqlParameter("sPassWord", sPassWord)); 52 cmd.ExecuteNonQuery(); 53 } 54 } 55 } 56 } 57 MessageBox.Show("導入成功"); 58 } 59 } 60 } 61 }
10、手機號碼歸屬地查詢省市下拉列表實例
(1、數據庫資源-全國省市數據庫 :http://www.programfan.com/blog/article.asp?id=28128
(2、數據庫連接:大概有兩種形式
<add key="" value /?
<add name="" connectonstring="" /?
這兩方法對應的后台訪問方式不一樣的
第一種:System.Configuration.ConfigurationManager.AppSettings["myConn"]
第二種:ConfigurationManager.ConnectionStrings["myConn"].ConnectionString
(3、要在類庫中找到ConfigurationManager.ConnectionStrings需要添加System.configuration
(4、遇到一個問題,是這樣,因為同一個解決方案里我建立了多個項目,項目中基於數據庫服務文件名字起的差不多(我都是沒改名,自動生成的名字),所以導致后
面在生成調試的時候,總是遇到“數據庫未創建實例”這樣的錯誤。
下面是手機號碼歸屬地查詢省市下拉列表實例:

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.Data.SqlClient; 10 using System.Configuration; 11 12 namespace myAdoNet02 13 { 14 public partial class Form3 : Form 15 { 16 public Form3() 17 { 18 InitializeComponent(); 19 } 20 //初始化 21 22 private void Form3_Load(object sender, EventArgs e) 23 { 24 string myconStr = ConfigurationManager.ConnectionStrings["myConStr"].ConnectionString; 25 26 using (SqlConnection conn = new SqlConnection(myconStr)) 27 { 28 conn.Open(); 29 using (SqlCommand cmd = conn.CreateCommand()) { 30 cmd.CommandText = "select * from promary"; 31 using (SqlDataReader reader = cmd.ExecuteReader()) { 32 while (reader.Read()) { 33 //構造model類 34 Promary p = new Promary(); 35 //將數據庫中的數據賦值給model類中的屬性值 36 p.ID = reader.GetInt32(reader.GetOrdinal("proID")); 37 p.sName = reader.GetString(reader.GetOrdinal("proName")); 38 Console.WriteLine(p.ID); 39 Console.WriteLine(p.sName); 40 Console.WriteLine(p); 41 省.Items.Add(p); 42 } 43 } 44 } 45 } 46 } 47 //選擇省后,查看市 48 private void 省_SelectedIndexChanged(object sender, EventArgs e) 49 { 50 市.Items.Clear();//清楚舊數據 51 Promary p2 = (Promary)省.SelectedItem; 52 int proID = p2.ID; 53 54 string myConStr = ConfigurationManager.ConnectionStrings["myConStr"].ConnectionString; 55 using (SqlConnection conn = new SqlConnection(myConStr)) 56 { 57 conn.Open(); 58 using(SqlCommand cmd=conn.CreateCommand()){ 59 cmd.CommandText = "select * from city where proID=@ID"; 60 cmd.Parameters.Add(new SqlParameter("ID", proID)); 61 using (SqlDataReader reader = cmd.ExecuteReader()) { 62 while (reader.Read()) { 63 string sCityName = reader.GetString(reader.GetOrdinal("cityName")); 64 市.Items.Add(sCityName); 65 } 66 } 67 } 68 } 69 } 70 71 class Promary 72 { 73 //下拉框的DisplayMember要設置為sName,才能顯示出來 74 public string sName { set; get; } 75 public int ID { set; get; } 76 } 77 78 } 79 }
配置文件App.config

1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <connectionStrings> 4 <add name="myConStr" connectionString="Data Source=.\SQLEXPRESS;AttachDBFilename=|DataDirectory|\Database1.mdf; 5 Integrated Security=True;Connect Timeout=30;User Instance=True"/> 6 </connectionStrings> 7 </configuration>
11、手機號碼歸屬地查詢
后台代碼:

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.Data.SqlClient; 10 using System.Configuration; 11 using System.IO; 12 13 namespace 手機歸屬地導入查詢 14 { 15 public partial class Form1 : Form 16 { 17 public Form1() 18 { 19 InitializeComponent(); 20 } 21 22 private void button1_Click(object sender, EventArgs e) 23 { 24 25 FolderBrowserDialog dlg = new FolderBrowserDialog(); 26 if (dlg.ShowDialog() != DialogResult.OK) 27 { 28 return; 29 } 30 string path = dlg.SelectedPath; 31 //清除數據 32 String connStr = ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString; 33 using (SqlConnection conn = new SqlConnection(connStr)) 34 { 35 conn.Open(); 36 using (SqlCommand cmd = conn.CreateCommand()) 37 { 38 cmd.CommandText = "delete from T_PhoneInfo"; 39 cmd.ExecuteNonQuery(); 40 } 41 } 42 43 44 MessageBox.Show("11!"); 45 string[] files = Directory.GetFiles(path, "*.txt", SearchOption.AllDirectories); 46 47 using (SqlConnection conn = new SqlConnection(connStr)) 48 { 49 conn.Open(); 50 using (SqlCommand cmd = conn.CreateCommand()) 51 { 52 cmd.CommandText = "Insert into T_PhoneInfo(sEndNo,sName,sStartNo) values(@sEndNo,@sName,@sStartNo)"; 53 54 foreach (string file in files)//遍歷文件名 55 { 56 string 運營商名稱 = Path.GetFileNameWithoutExtension(file); 57 //不用StreamReader,因為文件很小, 58 string[] lines = File.ReadAllLines(file, Encoding.Default); 59 //一次性加載,也不占多少內存,ReadAllLines默認編碼是UTF-8 60 61 MessageBox.Show("22!"); 62 foreach (string line in lines) 63 { 64 string[] strs = line.Split('-'); 65 string 開始號碼 = strs[0]; 66 string 結束號碼 = strs[1]; 67 string 市 = strs[2]; 68 InsertExecuteNonQuery(結束號碼, 運營商名稱+市, 開始號碼); 69 } 70 } 71 } 72 } 73 MessageBox.Show("導入成功!"); 74 } 75 76 public int InsertExecuteNonQuery(string sEndNo, string sName, string sStartNo) 77 { 78 string sqlString = "Insert into T_PhoneInfo(sEndNo,sName,sStartNo) values(@sEndNo,@sName,@sStartNo)"; 79 String connStr = ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString; 80 81 using (SqlConnection connetion = new SqlConnection(connStr)) 82 { 83 connetion.Open(); 84 using (SqlCommand Command = new SqlCommand(sqlString, connetion)) 85 { 86 SqlParameter[] param = new SqlParameter[] 87 { 88 new SqlParameter("@sEndNo", sEndNo), 89 new SqlParameter("@sName", sName), 90 new SqlParameter("@sStartNo", sStartNo) 91 92 }; 93 Command.Parameters.AddRange(param); 94 return Command.ExecuteNonQuery(); 95 } 96 } 97 } 98 } 99 }
program.cs

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Windows.Forms; 5 6 namespace 手機歸屬地導入查詢 7 { 8 static class Program 9 { 10 /// <summary> 11 /// 應用程序的主入口點。 12 /// </summary> 13 [STAThread] 14 static void Main() 15 { 16 //(1)不要忘記把這段代碼放進來 17 //一定要放在最開始,否則提示成功也沒有導入到數據庫中 18 //(2)數據庫表設置主鍵 19 string dataDir = AppDomain.CurrentDomain.BaseDirectory; 20 MessageBox.Show(dataDir); 21 if (dataDir.EndsWith("\\bin\\Debug\\") 22 || dataDir.EndsWith("\\bin\\Release\\")) 23 { 24 //dataDir = System.IO.Directory.GetParent(dataDir).Parent.FullName; 25 dataDir=dataDir.Replace("\\bin\\Debug\\", ""); 26 MessageBox.Show(dataDir); 27 AppDomain.CurrentDomain.SetData("DataDirectory", dataDir); 28 } 29 30 Application.EnableVisualStyles(); 31 Application.SetCompatibleTextRenderingDefault(false); 32 Application.Run(new Form1()); 33 } 34 } 35 }
配置文件:
DataDirectory路徑無法讀取到,因為在DBbrowser里的mdf並不是debug中的mdf,所以改成絕對路就可以了
備注:如果配置文件不改為絕對路徑的話,需要改program.cs中

1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <connectionStrings> 4 <add name="ConnStr" connectionString="Data Source=.\SQLEXPRESS;AttachDBFilename=|DataDirectory|\phone.mdf; 5 Integrated Security=True;User Instance=True"/> 6 </connectionStrings> 7 </configuration> 8 <!--Connect Timeout=30;-->
12、DataSet的基本使用
(1、封裝一個SQLHelper類:(用於被其它代碼調用,以下為該類的完整代碼)
***1、該類中含有四個方法,分別是:ExecuteNonQuery(string sql, params SqlParameter[] parameters)、ExecuteScalar(string sql, params
SqlParameter[] parameters)、ExecuteReader(string sql, params SqlParameter[] parameters)和ExecuteDataTable(string sql, params
SqlParameter[] parameters)。
在封裝這個類之前稱簡單介紹幾點:
a、封裝一個SQLHelper類方便使用,提供ExecuteNonQuery(string sql, params SqlParameter[] parameters);ExecuteScalar(string sql,
params SqlParameter[] parameters);ExecuteReader(string sql, params SqlParameter[] parameters);ExecuteDataTable(string sql,
params SqlParameter[] parameters)等方法,網上有微軟提供的最全的SQLHelper類,是Enterprise Library中的一部分。
b、用SQLHelper重寫登錄程序
c、new SqlParameter("e",0)的陷阱
d、sqlconnection在程序中一直保持它open可以嗎?對於數據庫來說,連接是非常寶貴的資源,一定要用完不close或dispose。
***2、ExecuteScalar 和ExecuteNonQuery的區別
a、ExecuteScala 返回r結果集中第一行的第一列或空引用(如果結果集為空),返回的是一個object
b、ExecuteNonQuery針對Connection 執行 SQL 語句並返回受影響的行數,返回的是一個int型值。
SQLHelp.cs

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Data.SqlClient; 6 using System.Configuration; 7 using System.Data; 8 9 namespace 封裝 10 { 11 class SQLHelp 12 { 13 public static readonly string connStr = ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString; 14 /*優點:1、把數據庫連接代碼都放在SQLHelper中,使代碼更簡潔 15 * 2、使用DataTable可以隨意讀取數據庫,而之前做的用戶登錄使用的SqlReader只能逐行往前讀*/ 16 17 public static int ExecuteNonQuery(string sql, params SqlParameter[] parameters) 18 { 19 using (SqlConnection conn = new SqlConnection(connStr)) 20 { 21 conn.Open(); 22 using (SqlCommand cmd = conn.CreateCommand()) 23 { 24 cmd.CommandText = sql; 25 foreach (SqlParameter parameter in parameters) 26 { 27 cmd.Parameters.Add(parameter); 28 } 29 return cmd.ExecuteNonQuery(); 30 } 31 } 32 } 33 34 public static object ExecuteScalar(string sql, params SqlParameter[] parameters) 35 { 36 string connStr = ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString; 37 using (SqlConnection conn = new SqlConnection(connStr)) 38 { 39 conn.Open(); 40 using (SqlCommand cmd = conn.CreateCommand()) 41 { 42 cmd.CommandText = sql; 43 foreach (SqlParameter parameter in parameters) 44 { 45 cmd.Parameters.Add(parameter); 46 } 47 //執行查詢,並返回查詢所返回的結果集中第一行的第一列。忽略其它的行或列。 48 return cmd.ExecuteScalar(); 49 } 50 } 51 } 52 public static SqlDataReader ExecuteReader(string sql, params SqlParameter[] parameters) 53 { 54 string connStr = ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString; 55 using (SqlConnection conn = new SqlConnection(connStr)) 56 { 57 conn.Open(); 58 using (SqlCommand cmd = conn.CreateCommand()) 59 { 60 cmd.CommandText = sql; 61 foreach (SqlParameter parameter in parameters) 62 { 63 cmd.Parameters.Add(parameter); 64 } 65 return cmd.ExecuteReader(); 66 } 67 } 68 } 69 public static DataTable ExecuteDataTable(string sql, params SqlParameter[] parameters) 70 { 71 string connStr = ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString; 72 using (SqlConnection conn = new SqlConnection(connStr)) 73 { 74 conn.Open(); 75 using (SqlCommand cmd = conn.CreateCommand()) 76 { 77 cmd.CommandText = sql; 78 foreach (SqlParameter parameter in parameters) 79 { 80 cmd.Parameters.Add(parameter); 81 } 82 //執行查詢,並返回查詢所返回的結果集中第一行的第一列。忽略其它的行或列。 83 DataSet dataset = new DataSet(); 84 SqlDataAdapter adapter = new SqlDataAdapter(cmd); 85 adapter.Fill(dataset); 86 return dataset.Tables[0]; 87 } 88 } 89 } 90 } 91 }
Form1.cs

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.Configuration; 10 using System.Data.SqlClient; 11 using System.IO; 12 using 封裝.DataSet1TableAdapters; 13 14 namespace 封裝 15 { 16 public partial class Form1 : Form 17 { 18 public Form1() 19 { 20 InitializeComponent(); 21 } 22 23 private void button1_Click(object sender, EventArgs e) 24 { 25 //ExecuteNonQuery 插入數據 26 SQLHelp.ExecuteNonQuery("insert into T_PhoneInfo(sStartNo,sEndNo,sName) values(@sStartNo,@sEndNo,@sName)", new SqlParameter("sStartNo", "11"), new SqlParameter("sEndNo", "11"), new SqlParameter("sName", "gaug懂")); 27 MessageBox.Show("插入數據成功"); 28 } 29 30 private void button2_Click(object sender, EventArgs e) 31 { 32 //ExecuteScalar 查詢條數 33 object i = SQLHelp.ExecuteScalar("select count(*)from T_PhoneInfo"); 34 MessageBox.Show(Convert.ToString(i)); 35 } 36 37 private void button3_Click(object sender, EventArgs e) 38 { 39 //SqlDataReader 40 SqlDataReader reader = SQLHelp.ExecuteReader("select * from T_PhoneInfo"); 41 while (reader.Read()) 42 { 43 //運行到這里報錯,因為跟數據庫的連接已關閉,利用DataSet可以解決這類問題 44 string sName = reader.GetString(reader.GetOrdinal("sName")); 45 } 46 } 47 48 private void button4_Click(object sender, EventArgs e) 49 { 50 //注意只有在小數據量的時候才往DataSet里放, 51 //因為DataSet要占內存,大數據量的時候還是要用DataReader 52 string connStr = ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString; 53 //定義一個DataSet 54 DataSet dataset = new DataSet(); 55 //數據庫操作表 56 using (SqlConnection con = new SqlConnection(connStr)) 57 { 58 con.Open(); 59 using (SqlCommand cmd = con.CreateCommand()) 60 { 61 cmd.CommandText = "select * from T_PhoneInfo"; 62 SqlDataAdapter adapter = new SqlDataAdapter(cmd); //執行select語句(要把cmd傳進去) 63 adapter.Fill(dataset);//將執行結果得到的數據填充到dataset中 64 } 65 } 66 //數據庫操作列 67 ///取dataset的表中的第0條數據 68 DataTable table = dataset.Tables[0]; 69 for (int i = 0; i < table.Rows.Count; i++) 70 { 71 DataRow row = table.Rows[i]; 72 string sName = Convert.ToString(row["sName"]); 73 MessageBox.Show(sName); 74 } 75 } 76 77 private void button5_Click(object sender, EventArgs e) 78 { 79 DataTable table = SQLHelp.ExecuteDataTable("select * from T_PhoneInfo"); 80 for (int i = 0; i < table.Rows.Count; i++) 81 { 82 DataRow row = table.Rows[i]; 83 string sName = Convert.ToString(row["sName"]); 84 MessageBox.Show(sName); 85 } 86 } 87 88 89 90 } 91 }
(2、利用上述SQLHelper.cs類中的ExecuteDataTable(string sql, params SqlParameter[] parameters)方法,做一個登陸界面
Form1.cs

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.Configuration; 10 using System.Data.SqlClient; 11 using System.IO; 12 using 封裝.DataSet1TableAdapters; 13 14 namespace 封裝 15 { 16 public partial class Form1 : Form 17 { 18 public Form1() 19 { 20 InitializeComponent(); 21 } 22 23 private void button9_Click(object sender, EventArgs e) 24 { 25 //登陸 26 DataTable table = SQLHelp.ExecuteDataTable("select * from T_UserInfo where sUser=@sUser", new SqlParameter("sUser", txtUser.Text)); 27 if (table.Rows.Count <= 0) 28 { 29 MessageBox.Show("用戶名不存在"); 30 } 31 else 32 { 33 //用戶名存在,已經知道是哪一列了,要返回的行是從零開始的索引 34 DataRow row = table.Rows[0]; 35 int sErroTime = Convert.ToInt32(row["sErroTime"]); 36 if (sErroTime > 3) 37 { 38 MessageBox.Show("登陸次數過多"); 39 return; 40 } 41 string sPassWord = Convert.ToString(row["sPassWord"]); 42 if (sPassWord == txtPassWord.Text) 43 { 44 SQLHelp.ExecuteNonQuery("update T_UserInfo set sErroTime=0 where sUser=@sUser", new SqlParameter("sUser", txtUser.Text)); 45 MessageBox.Show("登陸成功"); 46 } 47 else 48 { 49 SQLHelp.ExecuteNonQuery("update T_UserInfo set sErroTime=sErroTime+1 where sUser=@sUser", new SqlParameter("sUser", txtUser.Text)); 50 MessageBox.Show("密碼錯誤!"); 51 } 52 53 } 54 } 55 56 } 57 }
(3、
**修改DataSet單擊事件如下:
a、可以更新行row["Name"]="sUser"、刪除行datatable.Rows.Remove()、新增行datatable.NewRow()。這一切都是修改的內存中的DataSet,並沒
有修改數據庫。
b、可以調用SqlDataAdapter的Update方法將對DataSet的修改提交到數據庫,Update方法有很多重載方法,可以提交整個DataSet、DataTable
或者若干DataRow。但是需要為SqlDataAdapter提供DeleteCommand、UpdateCommand、InsertCommand它才知道如何將對DataSet的修改提交
到數據庫,由於這幾個Command要求的格式非常苛刻,因此開發人員自己寫非常困難;可以用SqlCommandBuilder自動生成這幾個Command,
SqlCommandBuilder要求表必須有主鍵。
c、通過DataRow的RowState可以獲得行的狀態(刪除、修改、新增等);調用DataSet的GetChanges()方法得到變化的結果集,降低傳遞的資源
**測試強類型DataSet單擊事件
敲寫代碼前,還要添加一個數據集DataSet1.xsd文件,然后打開數據集,將表拖到數據集中:

1 private void button6_Click(object sender, EventArgs e) 2 { 3 //陷阱 4 //實參為0與不為0時,這兩種情況下將光標放在SqlParameter中按F12轉到定義就出現不同的重載函數的情況, 5 //非常詭異類型轉換陷阱! 6 SQLHelp.ExecuteDataTable("select * from T_Users where Id=@Id", new SqlParameter("Id", (object)0)); 7 //修改方法是在0前加上object 8 } 9 10 11 12 private void button7_Click(object sender, EventArgs e) 13 { 14 //修改DataSet 15 DataSet dataset = new DataSet(); 16 string connStr = ConfigurationManager.ConnectionStrings["ConnStr"].ConnectionString; 17 using (SqlConnection conn = new SqlConnection(connStr)) 18 { 19 conn.Open(); 20 using (SqlCommand cmd = conn.CreateCommand()) 21 { 22 cmd.CommandText = "select * from T_UserInfo"; 23 SqlDataAdapter adapter = new SqlDataAdapter(cmd); 24 adapter.Fill(dataset); 25 26 //修改Dataset中的數據 27 DataTable talbe = dataset.Tables[0]; 28 DataRow row = talbe.Rows[0]; 29 row["sUser"] = "lcy"; 30 31 talbe.Rows.RemoveAt(1);//刪除一行 32 DataRow otherRow = talbe.NewRow();//新加一行 33 //自動生成更新語句 34 SqlCommandBuilder builder = new SqlCommandBuilder(adapter); 35 //更新DataSet,同步DataSet中的數據到數據庫 36 adapter.Update(dataset); 37 } 38 //對於不返回任何鍵列信息的 SelectCommand,不支持 UpdateCommand 的動態 SQL 生成。 39 //解決方案:表要設置主鍵 40 } 41 42 } 43 44 private void button8_Click(object sender, EventArgs e) 45 { 46 //測試強類型DataSet 47 T_UserInfoTableAdapter adapter = new T_UserInfoTableAdapter(); 48 封裝.DataSet1.T_UserInfoDataTable data = adapter.GetData(); //獲取數據 49 50 for (int i = 0; i < data.Count; i++) 51 { 52 封裝.DataSet1.T_UserInfoRow userRow = data[i]; 53 MessageBox.Show(userRow.sUser); 54 } 55 }
(4 、可空數據類型

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace 可空數據類型 7 { 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 string s1 = null; 13 //int i1=null; 14 int? i2 = 0; 15 int? i3 = null;//int? →可空的int,解決數據庫和C#對於int是否可以為null的不同所設置的 16 if (i3 == null) 17 { 18 Console.WriteLine("i3為空"); 19 } 20 else 21 { 22 i3++; 23 int i4 = (int)i3; //將可空的數據賦給不可空的,會報錯,加(int)i3以保證i3一定不為空 24 Console.WriteLine("i3不為空,i3++={0}", i3); 25 } 26 if (i3.HasValue) 27 { 28 int i4 = i3.Value; 29 Console.WriteLine("i3不為空"); 30 } 31 else 32 { 33 Console.WriteLine("i3為空"); 34 } 35 int i6 = 10; 36 int? i5 = i6; //將不可空的賦給可空的,不會報錯 37 } 38 }
(5、強類型DataSet判斷數據庫字段是否為null,強類型DataSet登陸,數據庫連接的連續性

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using 封裝.DataSet1TableAdapters; 10 using System.Diagnostics; 11 12 namespace 封裝 13 { 14 public partial class Form2 : Form 15 { 16 public Form2() 17 { 18 InitializeComponent(); 19 } 20 21 private void button1_Click(object sender, EventArgs e) 22 { 23 //判斷數據庫字段是否為空 24 T_UserInfoTableAdapter adapter = new T_UserInfoTableAdapter(); 25 封裝.DataSet1.T_UserInfoDataTable table = adapter.GetData(); 26 封裝.DataSet1.T_UserInfoRow row = table[1]; 27 28 if (row.IssPassWordNull()) 29 { 30 table[1].sPassWord = "888888"; 31 adapter.Update(table); 32 MessageBox.Show("密碼為空,已重置密碼"); 33 } 34 else { 35 MessageBox.Show("密碼為:"+table[0].sPassWord); 36 } 37 38 } 39 40 private void button2_Click(object sender, EventArgs e) 41 { 42 //DataSet 密碼登陸 43 T_UserInfoTableAdapter adapter = new T_UserInfoTableAdapter(); 44 封裝.DataSet1.T_UserInfoDataTable table = adapter.GetDataByUser(txtUser.Text); 45 46 if (table.Count <= 0) 47 { 48 MessageBox.Show("用戶不存在"); 49 } 50 else { 51 封裝.DataSet1.T_UserInfoRow row = table[0]; 52 if (row.sErroTime > 3) 53 { 54 MessageBox.Show("登陸次數過多"); 55 return; 56 } 57 else { 58 if (row.sPassWord == txtPassWord.Text) 59 { 60 adapter.UpdateErrorTimeBack(row.sUser); 61 MessageBox.Show("登陸成功"); 62 } 63 else { 64 adapter.UpdateErrorTimeAdd(row.sUser); 65 MessageBox.Show("登陸失敗,密碼錯誤"); 66 } 67 } 68 } 69 70 } 71 72 private void button3_Click(object sender, EventArgs e) 73 { 74 75 Stopwatch gameTime = new Stopwatch(); 76 gameTime.Start(); 77 T_UserInfoTableAdapter adapter = new T_UserInfoTableAdapter(); 78 79 /*慢方法:數據連接是間斷的 80 for (int i = 0; i < 3000; i++) 81 { 82 adapter.Insert(i.ToString(),i.ToString(),0); 83 }*/ 84 85 /*快方法:數據連接是連續的*/ 86 adapter.Connection.Open(); 87 for (int i = 0; i < 3000; i++) 88 { 89 //先刪除上個例子的數據 adapter.Delete(i.ToString(), i.ToString(), 0); 90 adapter.Insert(i.ToString(), i.ToString(), 0); 91 } 92 adapter.Connection.Close(); 93 94 gameTime.Stop(); 95 96 MessageBox.Show(gameTime.Elapsed.ToString()); 97 } 98 99 } 100 }