C#連接SQL Server數據庫完整指南,整合了ADO.NET原生連接與Entity Framework Core兩種實現方式。
這篇文件詳細介紹C#代碼連接
數據庫的通用操作
數據庫鏈接功能 數據庫的增刪改查操作
? 1 配置全局數據庫鏈接字符串 App.config
2 獲取數據庫鏈接字符串
先在App.config配置連接字符串
<connectionStrings>
//name 自定義名稱 ?服務器名稱Server=ip地址 端口號;數據庫名稱 賬號-密碼
<add name="c1" connectionString="Server=.,1433;DataBase=SMDB;Uid=sa;Pwd=123456"/>
</connectionStrings>
server=.
:指定服務器名稱為?.(自己計算機)
,表示數據庫服務器位于本地計算機上。.用于指代本地主機。
database=SMDB
:指定要連接的數據庫名稱為?SMDB
。這意味著連接成功后,將在?SMDB
數據庫上執行數據庫操作。
uid=sa
:指定用戶身份驗證使用的用戶名為?sa
。sa
?是 SQL Server 中的系統管理員賬戶。
pwd=123456
:指定用戶身份驗證使用的密碼為?123456
。
? ?//獲取
public static readonly string connstring = ConfigurationManager.ConnectionStrings["c1"].ToString();
注:也可以在c#創建字符串來設置連接字符串在進行獲取
?* 執行sql命令幾個方法
* 1 cmd.ExCuteNonQuery 添加數據(insert into) 修改數據update 刪除數據delete
* 2 cmd.ExcuteScalar ? select count(*)
* 3 cmd.ExcuteReader ? 返回的是sqlDatareader 管道 需要使用while循環, select *
* 4 SqlDataAdapter da = new DataAdapter(cmd) ,select * 場景
展示案例
獲取單一結果的方法 列如 記錄個數等功能
//獲取單一結果的方法 列如 記錄個數等功能
public static object GrSigleResult(string sql)
{//1創建數據庫連接 SqlConnection=new SqlConnection(connstring);//2創建sql命令SqlCommand cmd=new SqlCommand(sql,conn)//打開連接執行命令try{conn.open();return cmd.ExecuteScalar();}catch(Exception){throw;}finally{conn.Close();}
}方法調用:// 獲取總人數public static int GetStudentCount(){string sql = "select count(*) from Students";return Convert.ToInt32(SQLHelper.GrtSigleResult(sql));}
執行增刪改查操作
//執行增刪改查操作
public static int Update(string sql)
{SqlConnection conn=new SqlConnection(connstring);SqlCommand cmd=new SqlCommand(sql,conn);try{conn.open();return cmd.ExecuteNonQuery();}catch(Exception){throw;}finally{conn.Close();}
}
方法調用:
public static bool ClockInSuccess(Attendance ad)
{string sql = "insert into Attendance(CarNo) Values('{0}')";sql = string.Format(sql,ad.CardNo);try{SQLHelper.Update(sql);return true;}catch (Exception){throw;}
}
SqlDataReader 存儲數據庫數據 獲取數據的所有記錄 要用while循環去讀
public static SqlDataReader GetReader(string sql){SqlConnection conn = new SqlConnection(connstring);SqlCommand cmd = new SqlCommand(sql,conn);try{conn.Open();return cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection);}catch (Exception){throw;}}
方法調用:1 返回的是對象類型public static Student GetStudentByCardNo(string cardNo){string sql = "select StudentId,StudentName,Gender,Birthday,StudentIdNo,PhoneNumber,ClassName,StudentAddress,CardNo,StuImage from Students ";sql += "inner join StudentClass on Students.ClassId = StudentClass.ClassId ";sql += "where CardNo = '{0}'";sql = string.Format(sql, cardNo);SqlDataReader r = SQLHelper.GetReader(sql);Student student = null;if (r.Read()){student = new Student(){StudentId = Convert.ToInt32(r["StudentId"]),StudentName = r["StudentName"].ToString(),Gender = r["Gender"].ToString(),BirthDay = Convert.ToDateTime(r["Birthday"]),StudentIdNo = r["StudentIdNo"].ToString(),PhoneNumber = r["PhoneNumber"].ToString(),ClassName = r["ClassName"].ToString(),StudentAddress = r["StudentAddress"].ToString(),CarNo = r["CardNo"].ToString(),StuImage = r["StuImage"] == null ? "" : r["StuImage"].ToString(),};}r.Close();return student;}
2返回list集合public static List<Student> GetScoreList(string cname){//全校成績string sql = "select Students.StudentId, StudentName,ClassName,Gender,CSharp,SqlserverDB from Students inner join ScoreList on Students.StudentId=ScoreList.StudentId inner join StudentClass on StudentClass.ClassId = Students.ClassId ";if (cname != null && cname.Length != 0){//按照班級查詢sql += "where ClassName = '" + cname + "'";}SqlDataReader r = SQLHelper.GetReader(sql);List<Student> list = new List<Student>();while (r.Read()){list.Add(new Student(){StudentId = Convert.ToInt32(r["StudentId"]),StudentName = r["StudentName"].ToString(),Gender = r["Gender"].ToString(),ClassName = r["ClassName"].ToString(),CSharp = Convert.ToInt32(r["CSharp"]),SqlserverDB = Convert.ToInt32(r["SqlserverDB"]),});}r.Close();return list;}
獲取所有的記錄 返回的是dataset數據類型 不要逐條給實體類字段進行賦值
public static DataSet GetDateSet(string sql)
{SqlConnection conn = new SqlConnection(connstring);SqlCommand cmd = new SqlCommand(sql,conn);DataSet ds=new DataSet();SqlDataAdapter da=new SqlDataAdapter(cmd)try{conn.Open();da.Fill(ds); // 把數據表數據填充在dataset集合中return ds;}catch (Exception){throw;}finally { conn.Close() ; }
}
方法調用:/// <summary>/// 獲取所有成績的方法/// </summary>/// <returns></returns>public static DataSet GetAllScore(){string sql = "select Students.StudentId,StudentName,ClassName,Gender,PhoneNumber,CSharp,SqlserverDB from ScoreList inner join Students on Students.StudentId = ScoreList.StudentId inner join StudentClass on StudentClass.ClassId = Students.ClassId";return SQLHelper.GetDateSet(sql);}
Ui:private DataSet ds = null; // 放置所有的成績 數據集this.ds = ScoreService.GetAllScore();
獲取服務器時間
public static DateTime GetDateTime(){return Convert.ToDateTime(GrtSigleResult("select getdate()"));}
方法調用:DateTime t0 = Convert.ToDateTime(SQLHelper.GetDateTime().ToShortDateString());public static bool UpdateDBFormExcelByShiWu(List<string> list){SqlConnection conn = new SqlConnection(connstring);SqlCommand cmd = new SqlCommand();cmd.Connection = conn;try{conn.Open();// 開啟事物cmd.Transaction = conn.BeginTransaction();// 把list里面指令添加事務中foreach (string s in list){cmd.CommandText = s;cmd.ExecuteNonQuery();}cmd.Transaction.Commit();return true;}catch (Exception ex){MessageBox.Show("添加失敗," + ex);return false;}finally{conn.Close();}}
方法調用:public static bool SaveDataToDB(List<Student> list){// 定義sql語句StringBuilder sql = new StringBuilder("insert into Students ");sql.Append("(StudentName,Gender,BirthDay,StudentIdNo,CardNo,Age,PhoneNumber,StudentAddress,ClassId) ");sql.Append("values ");sql.Append("('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}');");// 2 創建一個保存sql語句的集合List<string> sqlList = new List<string>();// 3 遍歷傳遞過來的學生集合對象int i = 1213;foreach (Student student in list){string s = string.Format(sql.ToString(), student.StudentName, student.Gender,student.BirthDay.ToString("yyyy-MM-dd"), student.StudentIdNo, student.CarNo+i, student.Age,student.PhoneNumber, student.StudentAddress, student.ClassId);sqlList.Add(s);i++;}return SQLHelper.UpdateDBFormExcelByShiWu(sqlList);}
SQL注入
當我們要在登錄賬號密碼時 不知道賬號密碼 可以字符串拼接 直接登錄 或一些其他刪除表等操作
比如用戶輸入: ' or 1=1 -- 就可以成功登錄了'是跟前面輸入的sql語句連接 or 1=1 當條件成立時 然后就可以成功登錄 --是省略后面的 甚至可以執行刪庫的操作: '; drop database xxxx
防止sql注入的方法就是避免直接將用戶輸入的內容拼接到sql語句中
使用帶參數的sql語句執行數據庫操作就可以避免sql注入
使用帶參數的sql語句不需要關注sql語句帶引號的問題
在sql語句中 使用@xxx 定義sql參數
案列:
// 2、在SqlCommand對象中為sql參數賦值// 添加參數的方法1(推薦)// cmd.Parameters.AddWithValue("@abc", textBox1.Text); // 添加一個參數,并為參數賦值// cmd.Parameters.AddWithValue("@efg", textBox2.Text);// 添加參數的方法2//cmd.Parameters.Add("@abc", SqlDbType.VarChar); // 添加一個參數,并指定參數的類型//cmd.Parameters["@abc"].Value = textBox1.Text; // 為@abc參數賦值//cmd.Parameters.Add("@efg", SqlDbType.VarChar);//cmd.Parameters["@efg"].Value = textBox2.Text;// 添加參數的方法3//cmd.Parameters.Add(new SqlParameter("@abc", textBox1.Text));//cmd.Parameters.Add(new SqlParameter("@efg", textBox2.Text));// 添加參數的方法4(推薦)SqlParameter[] parameters = new SqlParameter[]{new SqlParameter("@abc", textBox1.Text),new SqlParameter("@efg", textBox2.Text)};cmd.Parameters.AddRange(parameters);封裝幾個類的方法/// <summary>/// 執行增刪改操作/// </summary>/// <param name="sql">要執行的sql語句</param>/// <param name="parameter">傳遞的sql參數</param>/// <returns></returns>public static int Update(string sql, params SqlParameter[] parameter){SqlCommand cmd = new SqlCommand(sql, conn);cmd.Parameters.AddRange(parameter);return cmd.ExecuteNonQuery();}/// <summary>/// 執行查詢操作/// </summary>/// <param name="sql">要執行的sql語句</param>/// <param name="parameter">傳遞的sql參數</param>/// <returns></returns>public static SqlDataReader GetData(string sql, params SqlParameter[] parameter){SqlCommand cmd = new SqlCommand(sql, conn);cmd.Parameters.AddRange(parameter);return cmd.ExecuteReader();}/// <summary>/// 執行單行單列的查詢操作/// </summary>/// <param name="sql">要執行的sql語句</param>/// <param name="parameter">傳遞的sql參數</param>/// <returns></returns>public static object GetObject(string sql, params SqlParameter[] parameter){SqlCommand cmd = new SqlCommand(sql, conn);cmd.Parameters.AddRange(parameter);return cmd.ExecuteScalar();}
下一節講EF(Entity Framework)?不需要寫連接字符串 因為在寫字符串也很難查找報錯地方因為字符串寫錯問題 以及連接創建許多代碼 和查詢等還需要注意SQL防注入?