專題 ASP.NET + DB

Similar documents
untitled

untitled

投影片 1

untitled

導讀 ASP.NET HTML ASP 第一篇 基礎篇第 1 章 認識 ASP.NET ASP.NET ASP.NET ASP.NET ASP.NET 第 2 章 認識 Visual Studio 20 開發環境 Visual Studio 20 Visual Studio 20 第二篇 C# 程式

untitled

2 ADO.NET Internet 1.2

教案模板4-2

ADO.NET 資料庫存取架構

主程式 : public class Main3Activity extends AppCompatActivity { ListView listview; // 先整理資料來源,listitem.xml 需要傳入三種資料 : 圖片 狗狗名字 狗狗生日 // 狗狗圖片 int[] pic =new

untitled

目錄

6-1 Table Column Data Type Row Record 1. DBMS 2. DBMS MySQL Microsoft Access SQL Server Oracle 3. ODBC SQL 1. Structured Query Language 2. IBM

一 個 SQL Injection 實 例 的 啟 示 頁 2 / 6 因 此, 在 知 名 網 站 上 看 到 SQL Injection, 讓 人 驚 心, 卻 不 意 外 網 站 專 案 外 包 是 目 前 業 界 的 常 態, 而 在 價 格 取 勝 的 制 度 下, 低 價 得 標 的 S

第 一 章 資料庫概念

2 WF 1 T I P WF WF WF WF WF WF WF WF 2.1 WF WF WF WF WF WF

Microsoft Word - 01.DOC

<ADB6ADB1C25EA8FAA6DB2D4D56432E706466>

<463A5CC2A4B6ABD1A7D4BA5CBDCCD1A7D6B8C4CFD7DC5CA1B C B3CCD0F2C9E8BCC6A1B7BFCEB3CCD6B8C4CF2E646F63>

RUN_PC連載_12_.doc

(Microsoft PowerPoint -

Microsoft Office SharePoint Server MOSS Web SharePoint Web SharePoint 22 Web SharePoint Web Web SharePoint Web Web f Lists.asmx Web Web CAML f

RUN_PC連載_8_.doc

untitled

untitled

概述

使用手冊

<4D F736F F D20C9CFBAA3CAD0BCC6CBE3BBFAB5C8BCB6BFBCCAD4C8FDBCB6BFBCCAD4B4F3B8D95FBDA8D2E9B8E55F5F E646F63>

untitled

投稿類別:資訊類

建立Android新專案

1 1 大概思路 创建 WebAPI 创建 CrossMainController 并编写 Nuget 安装 microsoft.aspnet.webapi.cors 跨域设置路由 编写 Jquery EasyUI 界面 运行效果 2 创建 WebAPI 创建 WebAPI, 新建 -> 项目 ->

多媒體應用 13 新增專案並完成版面配置 <ExMusic01> <activity_main.xml> ImageView ID imgplay ImageView ID imgstop ImageView ID imgfront TextView ID txtsong TextView ID t

投影片 1

Microsoft Word - PHP7Ch01.docx

untitled

untitled

untitled

投影片 1

RunPC2_.doc

《大话设计模式》第一章

FileMaker 15 ODBC 和 JDBC 指南

AL-M200 Series

RUN_PC連載_10_.doc

Microsoft PowerPoint - VB14.ppt

第七章

FileMaker 16 ODBC 和 JDBC 指南

Microsoft Word - ch04三校.doc

目錄... ivv...vii Chapter DETECT

untitled

學 科 100% ( 為 單 複 選 題, 每 題 2.5 分, 共 100 分 ) 1. 請 參 閱 附 圖 作 答 : (A) 選 項 A (B) 選 項 B (C) 選 項 C (D) 選 項 D Ans:D 2. 下 列 對 於 資 料 庫 正 規 化 (Normalization) 的 敘

Chapter 00 導論

13 根 据 各 种 网 络 商 务 信 息 对 不 同 用 户 所 产 生 的 使 用 效 用, 网 络 商 务 信 息 大 致 可 分 为 四 级, 其 中 占 比 重 最 大 的 是 ( A ) A 第 一 级 免 费 信 息 B 第 二 级 低 收 费 信 息 C 第 三 级 标 准 收 费

上海市教育考试院关于印发新修订的

PPBSalesDB.doc

untitled

1 Framework.NET Framework Microsoft Windows.NET Framework.NET Framework NOTE.NET NET Framework.NET Framework 2.0 ( 3 ).NET Framework 2.0.NET F

f2.eps

Microsoft Word - InoTouch Editor编程软件手册 doc

EJB-Programming-4-cn.doc

7 DataSet DataSet TableColumnDataSet DataSet NOTE DataSet DataAdapterDataSetDataAdapter DataSet DataSetDataSetDataSet NorthwindDataSet DataSet Dim Nor

Microsoft Word - RFID資料庫系統設計.doc

四川省普通高等学校

幻灯片 1

用手機直接傳值不透過網頁連接, 來當作搖控器控制家電 ( 電視遙控器 ) 按下按鍵發送同時會回傳值來確定是否有送出 問題 :1. 應該是使用了太多 thread 導致在傳值上有問題 2. 一次按很多次按鈕沒辦法即時反應

R D B M S O R D B M S R D B M S / O R D B M S R D B M S O R D B M S 4 O R D B M S R D B M 3. ORACLE Server O R A C L E U N I X Windows NT w w

(HMI) IO A

Microsoft Word - 苹果脚本跟我学.doc

The golden pins of the PCI card can be oxidized after months or years

untitled

Spyder Anaconda Spyder Python Spyder Python Spyder Spyder Spyder 開始 \ 所有程式 \ Anaconda3 (64-bit) \ Spyder Spyder IPython Python IPython Sp

致理技術學院資訊管理學系專題企劃書格式建議書

Android Service

星星排列 _for loop Protected Sub Page_Load(ByVal sender As Object, ByVal e As Dim h As Integer = 7 'h 為變數 ' Dim i, j As Integer For i = 1 To h

1: public class MyOutputStream implements AutoCloseable { 3: public void close() throws IOException { 4: throw new IOException(); 5: } 6:

untitled

Chapter 16 集合

Microsoft Word - ASP2DB1002.doc

附件3:

<4D F736F F D20C8EDC9E82DCFC2CEE7CCE22D3039C9CF>

封面-12

新版 明解C++入門編

( )... 5 ( ) ( )

全国计算机技术与软件专业技术资格(水平)考试

Flexsim: (Open DataBase Connectivity, ODBC)

IsPostBack 2

ebook39-5

Transcription:

ASP.NET + 資料庫 建國科技大學資管系饒瑞佶 2015/9 V1 2016/3 V2

幾件一定要會的事 資料庫架構 SQL 指令.NET 資料庫存取架構

資料庫種類 檔案式 vs. Server 式 階層式 網狀式 關聯式 NOSQL

資料庫系統 資料庫 資料庫管理者 應用程式

資料庫 內容 SQL Server (server 式 ) 使用北風 (Northwind) 或 POS 範例資料庫 ASP.NET 資料庫設計模式 資料庫安全 SQL Injection 大小寫驗證 密碼強度等

匯入範例資料庫到 SQL Server

SQL Server 最新版 SQL Server 2014 有 Express 版本可以使用 管理工具為 SQL Server Management Studio

連結 SQL Server 管理方式 透過 SQL Server 管理工具 Management Studio 帳號 + 密碼 (SQL Server 驗證 ) Windows 驗證 透過 VS.Net Client 端連結工具 伺服器總管

SQL Server Management Studio

2 種驗證模式 SQL Server 驗證 需要帳號密碼 支援遠端連線 Windows 驗證 需要 Windows 管理者權限 忘記帳密時使用 伺服器名稱 : IP 或電腦名稱 \SQLEXPRESS 先試試 Windows 驗證, 確定 SQL Server 活著

SQL Server 驗證 IP 驗證方式 帳號 密碼

操作技巧答案在左邊, 答案在右鍵

SQL Server 附加 / 卸離資料庫 mdf 與 ldf 檔案需要成對

附加時若有錯誤 一般是權限問題 請將 mdf 與 ldf 檔案的權限開給 users, 並設定成完全控制即可

關閉 SQL Server

關閉 SQL Server

轉移或備份 SQL Server 資料庫 需要同時搬移或備份 mdf 與 ldf 兩個檔案 可能的位置 ( 要看當初安裝時設定的目錄 ) C:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\DATA 搬移或備份時應先關閉 SQL Server

加入留言板資料庫與資料表 留言主表 (Guestbook) 與副表 (Reply) 設定關聯

設定關聯

設定資料庫權限

SQL Server 權限 帳號決定可以使用的權限 : 未來就用這組帳號密碼登入與使用資料庫 存取權限 : 只能查詢資料 可以修改資料 可以修改結構 各資料庫可以設定各自的帳號 密碼與權限

SQL Server 權限 新增帳號 目前大家使用這組帳號

SQL Server 權限 帳號請自行設定 密碼請自行設定 是否可以使用權限 設定帳號原則

SQL Server 權限 設定帳號可以使用的資料庫 ( 可複選 ) 存取權限 資料 : db_datareader db_datawriter 結構 : db_owner

.NET 連結資料庫基本觀念

資料庫程式設計的基本概念 有人幫忙連接資料庫 ( 資料庫連接物件 ) 有人幫忙執行 SQL 指令 有人幫忙顯示 ( 介面設計與顯示物件 ) 但問題是 : 資料庫那麼多, 怎麼處理? 有沒有簡易的方法?

ASP.NET 資料庫設計模式 DB ADO.NET CommandBuilder 物件 Connection 物件 Command 物件 DataAdapter 物件 DataReader 物件 ExecteNonQuery 可異動資料 DataReader 物件 ExecuteReader 唯讀 DataSet 物件 On-line 線上作業模式 Off-line 離線作業模式

設計方式 建構在 ADO.NET 架構上 使用工具箱中既有物件 ( 拖拉放 + 設定模式 ) 自己寫程式處理所有細節

先來個簡單的拖拉放 資料庫 << SQL Server 有人幫忙連接 ( 資料庫連接物件 ) 與執行 SQL 指令 SqlDataSource 物件 有人幫忙顯示 ( 介面設計與顯示物件 ) GridView 物件

兩個物件就搞定

設定連線資料庫 連線字串

資料庫連線設定 這裡選擇剛建立的留言板資料庫

這裡最好要勾 Yes, 將資料存在 web.config 內以後統一使用, 維護也比較方便

注意 連線字串只要一個, 存放在 web.config 內就好, 以後才好維護 有兩種取用方式 透過物件 透過程式

連線字串 連線字串的格式要根據不同資料庫而定 那裡可以找到連線字串的說明? http://www.connectionstrings.com http://www.carlprothman.net/default.aspx?tabid=81

怎麼用 we.config 內的連線呢? 當初存入 we.config 內的名稱 String connstr = System.Web.Configuration.WebConfigurationManager.Connecti onstrings["connectionstringctumenu"].connectionstring.tos tring(); SqlConnection dbconn = new SqlConnection(connstr);

SQL 指令 新增刪除修改查詢都在這裡

設定顯示物件 GridView

先執行看看 沒有刪除與修改?

結果

加上新 / 刪 / 修 / 查 方法 1: 可以不用會 SQL 指令

刪除與修改出現了 勾起來後執行看看

結果 刪除加入確認詢問? 欄位轉成 TemplateField 設定 onclientclick 屬性 =return confirm( 確定要刪除? );

加上新 / 刪 / 修 / 查 方法 2: 自己寫 SQL 指令

一個 SQL 指令範例

透過 DetailsView 物件做新增

首先 GridView 開啟 Selection

設定 SqlDataSource2 直接選剛存的那個連線字串這樣大家就都共用同一個連線方式

DetailsView 連接到 SqlDataSource2

問題 如果到此都設定好了 那新 / 刪 / 修 / 查都有了 透過 DetailsView 新增 / 刪除後, 並沒有重整 GridView 畫面

重整畫面 選事件 重新讓 GridView 連結 SqlDataSource 就可以

欄位加入檢查條件

欄位加入檢查條件

DetailsView 加入控制項 以 Calendar 為例 protected void Calendar1_SelectionChanged(object sender, EventArgs e) { TextBox tt = (TextBox)DetailsView1.FindControl("Add_Day"); Calendar cc=(calendar)detailsview1.findcontrol("calendar1"); tt.text = cc.selecteddate.toshortdatestring() + " " + System.DateTime.Now.ToShortTimeString();

GridView 加入控制項 以 Calendar 為例 protected void Calendar2_SelectionChanged(object sender, EventArgs e) { TextBox tt = (TextBox)GridView1.Rows[rowIndex].FindControl("TextBox3"); Calendar cc = (Calendar)GridView1.Rows[rowIndex].FindControl("Calendar2"); tt.text = cc.selecteddate.toshortdatestring() + " " + System.DateTime.Now.ToShortTimeString(); static int rowindex; // 取得目前要修改的編號 protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e) { rowindex = e.neweditindex;

自己設計對應的新增版面 放在 Panel 中

自己設計對應的新增版面, 再對應到 InsertQuery 指令 Sqldatasource InsertQuery

日期另外處理 設定參數對應的物件

新增程式 protected void Button3_Click(object sender, EventArgs e) { SqlDataSource1.Insert(); Panel1.Visible = false;

處理留言空白與 enter( 新增 ) 首先修改新增參數 原來的參數設定要取消 protected void SqlDataSource1_Inserting(object sender, SqlDataSourceCommandEventArgs e) 處理新增 { e.command.parameters["@usercontent"].value = TextBox3.Text.Replace(" "," ").Replace("\n","<br>"); e.command.parameters["@contentday"].value = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

處理留言空白與 enter( 顯示 ) 將 usercontent 欄位轉成 template

處理留言空白與 enter( 顯示 ) protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) { if (e.row.rowtype == DataControlRowType.DataRow) { var lbldi = e.row.findcontrol("label1") as Label; // 內容 if (lbldi!= null) { lbldi.text = lbldi.text.tostring().replace("\n", "<br />"); 如果存入資料庫時沒有處理 \n

結果

加入查詢 需要版面 需要動態 SQL 指令 要想辦法把命令轉給 SqlDataSource 物件

程式只要一行 改變 sql 指令就可以 protected void Button1_Click(object sender, EventArgs e) { SqlDataSource1.SelectCommand = "select * from Guestbook where title like '%" + TextBox1.Text + "%'"; 所以已經很方便了, 但 SQL 指令還是不能省

GridView 物件其他操作

依條件改變狀態 protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) { // 設定列的寬度 if (e.row.rowtype == DataControlRowType.Header) { e.row.cells[0].width = 400; // 維護欄位 e.row.cells[0].backcolor = System.Drawing.Color.CornflowerBlue; e.row.cells[1].width = 200; // 編號 e.row.cells[2].width = 300; // 姓名 e.row.cells[3].width = 300; // 帳號 e.row.cells[4].width = 300; // 密碼 e.row.cells[5].width = 300; // 年齡 // 依據狀態設定列的顏色 if (e.row.rowtype!= DataControlRowType.DataRow) return; if (e.row.cells[11].text == " 有效 ") { e.row.backcolor = System.Drawing.Color.GreenYellow; else { e.row.backcolor = System.Drawing.Color.Pink; // 停權

圖片 放入其他物件

按鈕物件 放入其他物件

GridView 加入 Button 取得主鍵 PK protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e) { if (e.commandname == "abc") { int rowindex = int.parse(e.commandargument.tostring()); string val = this.gridview1.datakeys[rowindex].value.tostring(); Response.Write(val);

顯示照片 照片放在資料庫外 照片放在資料庫內

照片在資料庫外 先加入 ImageField 轉換成 TemplateField 設定連結照片所在外部的位置

透過 Generic Handler 照片在資料庫內

ImageHandler.ashx 照片在資料庫內 public class ImageHandler : IHttpHandler { public void ProcessRequest (HttpContext context) { string imageid = context.request.querystring["imid"]; SqlConnection con = new SqlConnection("Data Source=127.0.0.1;Initial Catalog=POS;Persist Security Info=True;User ID=sa;Password=1234"); con.open(); SqlCommand cmd = new SqlCommand("select picin from product where p_id=" + imageid, con); SqlDataReader dr = cmd.executereader(); dr.read(); context.response.binarywrite((byte[])dr[0]); con.close(); context.response.end(); public bool IsReusable { get { return false;

照片在資料庫內 先加入 TemplateField 加入 Image 物件 設定 DataBindings

將圖片存入資料庫 使用 FileUpload 物件

將圖片存入資料庫 // Save files to Folder and files path in database protected void btnupload_click(object sender, EventArgs e) { //Condition to check if the file uploaded or not if (fileupload1.hasfile) { int length = fileupload1.postedfile.contentlength; byte[] imgbyte = new byte[length]; HttpPostedFile img = fileupload1.postedfile; //set the binary data img.inputstream.read(imgbyte, 0, length); string filename = Path.GetFileName(fileUpload1.PostedFile.FileName); using (SqlConnection con = new SqlConnection(strCon)) { using (SqlCommand cmd = new SqlCommand()) { cmd.commandtext = "insert into MyImage (imagename,imagedata) values(@name,@data)"; cmd.parameters.addwithvalue("@name", filename); cmd.parameters.addwithvalue("@data", imgbyte); cmd.connection = con; con.open(); cmd.executenonquery(); con.close(); BindGridviewData();

檔案上傳 FileUpload 物件 ( 單一檔案 ) // 檔案上傳 Boolean fileok = false; String path = Server.MapPath("~/images/" + Session["modifyStoreID"] + "/"); if (FileUpload1.HasFile) { String fileextension = System.IO.Path.GetExtension(FileUpload1.FileName).ToLower(); String[] allowedextensions = { ".gif", ".png", ".jpeg", ".jpg" ; for (int i = 0; i < allowedextensions.length; i++) { if (fileextension == allowedextensions[i]) { fileok = true; 接下頁

檔案上傳 if (fileok) { try { FileUpload1.PostedFile.SaveAs(path + FileUpload1.FileName); Label6.Text = " 檔案上傳完成!"; listimages(); catch (Exception ex) { Label6.Text = " 檔案無法上傳!"; else { Label6.Text = " 檔案格式錯誤!";

多檔案一次上傳 一定要.net framework 4.5 以上

// 檔案上傳 Boolean fileok = false; String path = Server.MapPath("~/images/" + Session["modifyStoreID"] + "/"); HttpFileCollection uploadedfiles = Request.Files; Label6.Text = string.empty; for (int i = 0; i < uploadedfiles.count; i++) { HttpPostedFile userpostedfile = uploadedfiles[i]; try { if (userpostedfile.contentlength > 0) { // 限制檔案大小, 限制為 2MB int filesize = userpostedfile.contentlength; if (filesize > 2100000) { Label6.Text = " 檔案大小上限為 2MB, 目前上傳的檔案 [" + userpostedfile.filename + "] 超過大小, 無法上傳 "; return; userpostedfile.saveas(path + "\\" + Path.GetFileName(userPostedFile.FileName)); fileok = true; catch (Exception Ex) { Label6.Text += "Error: <br>" + Ex.Message; fileok = false; 接下頁

if (fileok) { try { FileUpload1.PostedFile.SaveAs(path + FileUpload1.FileName); Label6.Text = " 檔案上傳完成!"; listimages(); catch (Exception ex) { Label6.Text = " 檔案無法上傳!"; else { Label6.Text = " 檔案格式錯誤!";

改用 ListView 顯示

ListView 連結 DB 透過 SqlDataSource 物件 ( 直接設定連結就可以 ) 設定後並不會出現資料, 還需要設定 ListView 顯示資料

設定 ListView 顯示資料 Configure ListView

每列顯示筆數如果改變, 要記得同時設定 ItemTemplate 與 AlternatingItemTemplate 設定 ListView

設定 ListView 顯示資料 預覽 顯示樣式 外觀 啟用功能

result 自動就會有新增 / 刪除 / 修改功能

加入搜尋功能 protected void Button1_Click(object sender, EventArgs e) { SqlDataSource1.SelectCommand = "select * from customer where c_name like '%" + TextBox1.Text + "%'";

修改介面 例如修改預設按鈕文字 要設定 ItemTemplate 與 AlternatingTemplate

Image 可以直接設定 Binding 加入其他物件 Table 1x2 做排版 Button

Bind Image 資料庫內儲存照片檔名 ( 位置在 server 內固定位置, 例如 images)

透過 ListView 新增圖片 (I) 在 InsertTemplate 中加入 fileupload 控制項

透過 ListView 新增圖片 (II) 將要顯示圖片名稱欄位的輸入框 (id=xyz) 之 ClientIDMode 屬性設定為 Static 透過 JavaScript 將 Fileupload 選擇的圖片名稱顯示到輸入框內 <asp:fileupload ID="FileUpload1" runat="server" OnDataBinding="FileUpload1_DataBinding" onchange="getfilename(this.value);" /> <script> function getfilename(file) { // 檔案名稱 var filename = file.replace(/^.*[\\\/]/, '') document.getelementbyid('xyz').value = filename; </script>

透過 ListView 新增圖片 (II) Code in Insert button

protected void InsertButton_Click(object sender, EventArgs e) { FileUpload fu = (FileUpload)ListView1.InsertItem.FindControl("FileUpload1"); Boolean fileok = false; String path = Server.MapPath("~/images/"); if (fu.hasfile) { String fileextension = System.IO.Path.GetExtension(fu.FileName).ToLower(); String[] allowedextensions = { ".gif", ".png", ".jpeg", ".jpg" ; for (int i = 0; i < allowedextensions.length; i++) { if (fileextension == allowedextensions[i]) { fileok = true; if (fileok) { try { fu.postedfile.saveas(path + fu.filename); catch (Exception ex) { else { Code in Insert button

Bind Button 要抓到 ListView 內繫結的物件 ( 如 Button) 事件, 要設定 Button 的 CommandArgument 設定按下後要取得的值

撰寫 Button 事件 要取得上一頁的 p_id, 要用的是 Button_Command 事件, 而不是 Button_Click 事件

ListView + Session 購物車

Session 購物車 確定已經設定按鈕的 CommandArgument DataTable Cart = new DataTable(); // 存放購物車 DataRow objdr; // 每筆購物項目 protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { Session["ShoppingCart"] = ""; Response.Write("<script>alert(' 請選擇您要購買的物品 ');</script>");

如果要加入數量選擇或輸入到 ListView 將購買按鈕的事件改為 ListView1_ItemCommand 找到 TextBox2 var txt = ListView1.Items[e.Item.DataItemIndex].FindControl("TextBox2") as TextBox; 選擇的項目 index

購物按鈕 (I) protected void ListView1_ItemCommand(object sender, ListViewCommandEventArgs e) { var txt = ListView1.Items[e.Item.DataItemIndex].FindControl("TextBox2") as TextBox; if (Session["ShoppingCart"]=="") { // 購物車為空, 需要建立 DataTable 的結構 // 產品編號 Cart.Columns.Add(new DataColumn("ItemID",typeof(int))); // 數量 Cart.Columns.Add(new DataColumn("Quantity", typeof(int))); objdr = Cart.NewRow(); // 產生新列 objdr["itemid"] = e.commandargument; // 產品編號 objdr["quantity"] = txt.text; // 數量 Cart.Rows.Add(objDR); else

購物按鈕 (II) else { // 取出目前購物車內容, 判斷是否已經加入? Cart = (DataTable)Session["ShoppingCart"]; Boolean blnmatch = false; // 紀錄是否已經加入購物車 foreach(datarow objdr in Cart.Rows){ if (objdr["itemid"].tostring()==e.commandargument.tostring()) { int newnum = Convert.ToInt16(objDR["Quantity"]) + Convert.ToInt16(txt.Text); objdr["quantity"] = newnum; // 數量 blnmatch = true; break; if (!blnmatch) // 沒有買過 { objdr = Cart.NewRow(); // 產生新列 objdr["itemid"] = e.commandargument; // 產品編號 objdr["quantity"] = txt.text; // 數量 Cart.Rows.Add(objDR); Session["ShoppingCart"] = Cart; Response.Write(e.CommandArgument + " 已經加入購物車 ");

檢視購物車 protected void Button4_Click(object sender, EventArgs e) { // 檢視購物車 if (Session["ShoppingCart"]!= "") { Cart = (DataTable)Session["ShoppingCart"]; foreach (DataRow objdr in Cart.Rows) { Response.Write(" 編號 =" + objdr["itemid"] + "/ 數量 =" + objdr["quantity"] + "</br>"); else{ Response.Write(" 目前購物車是空的!"); 可以自己定義版面

寫程式連資料庫

再看回 ASP.NET 資料庫設計模式 DB ADO.NET CommandBuilder 物件 Connection 物件 Command 物件 DataAdapter 物件 DataReader 物件 ExecteNonQuery 可異動資料 DataReader 物件 ExecuteReader 唯讀 DataSet 物件 On-line 線上作業模式 Off-line 離線作業模式

上圖的物件是大架構 表示跟資料庫種類無關 可是現實是, 資料庫種類不完全相同 那要怎麼處理呢? 微軟把個別資料庫連結方式做分類, 放在名稱空間內 (namespace) 需要時再叫進來就可以 依據不同資料庫, 會在物件前面加上適當的冠詞

ADO.NET ADO.NET 是用來存取資料庫的物件集合 核心命名空間 : 一般 : System.Data, System.Data.Common SQL Server: System.Data.SqlClient Oracle: System.Data.OracleClient OleDB: System.Data.OleDb (Access) ODBC: System.Data.Odbc 利用 Using 指令參考 ADO.NET 物件

以 ON-LINE MODE 讀取資料為例

DB On-line mode CommandBuilder 物件 Connection 物件 Command 物件 DataAdapter 物件 DataReader 物件 ExecteNonQuery 可異動資料 DataReader 物件 ExecuteReader 唯讀 DataSet 物件 On-line 線上作業模式 Off-line 離線作業模式

DataReader 透過 DataReader 物件可以逐一讀取資料 DataReader = 只能下一筆 唯讀的讀取 根據要求將記錄以串流的方式傳回用戶端 佔用資料庫連線, 使用伺服端資源直到連線關閉 用戶端 DataReader 記錄 record record 資料庫引擎

資料庫存取五步驟 ADO.NET 存取資料時, 使用以下五大步驟 : 1. Using ADO.NET 物件 ( 依資料庫種類而定 ) 2. 開啟資料庫連線 DBMS+DB 層 (CONNECTION 物件 ) 3. 進行資料庫操作 ( 讀取 / 寫入 ) TABLE 層 (COMMAND+DATAREADER 物件 ) 4. 顯示資料 5. 關閉資料庫連線

DataReader 資料存取示意圖 DBMS DB TABLE CONNECTION 物件負責連結 DBMS 與 DB COMMAND 物件負責 SQL 指令 SQL SERVER 1. SERVER 位置 2. 帳號 3. 密碼 4. DATABASE Access 1. DATABASE DataReader 物件負責取出 DATA 連線字串

對應 (I) 1. Using ADO.NET 物件 ( 依資料庫種類而定 ) 2. 開啟資料庫連線 DBMS+DB 層 程式需要的是這個連線字串

對應 (II) 1. 進行資料庫操作 ( 讀取 / 寫入 ) TABLE 層 (COMMAND+DATAREADER 物件 ) 程式需要的是 SQL 指令

自己透過 Panel 顯示結果 // 連結資料庫 SqlConnection dbconn = new SqlConnection( 連線字串 "); dbconn.open(); // 開啟資料庫 SqlCommand dbcmd = new SqlCommand( SQL 指令 ", dbconn); SqlDataReader dbreader = dbcmd.executereader(); String result = "<table width='100%' border=1><tr>"; // 建立表格 // 顯示表頭 for (int col = 0; col < dbreader.fieldcount; col++) { result += "<td>" + dbreader.getname(col).tostring() + "</td>"; result += "</tr>"; // 顯示資料 while (dbreader.read()) { result += "<tr>"; for (int col = 0; col < dbreader.fieldcount; col++) { result += "<td>" + dbreader[dbreader.getordinal(dbreader.getname(col).tostring())].tostring() + "</td>"; result += "</tr>"; result += "</table>"; dbconn.close(); // 關閉資料庫 Panel1.Controls.Add(new LiteralControl(result));

改成用 Class 方式運作?

需要繼承 MyPage.cs 使用 DBOperation.cs 與 MyPage.cs // 設定起始事件, 設定 DB 連線字串 protected void Page_Init(object sender, EventArgs e) { // 設定連線字串 constr = 連線字串 "; // 設定要操作的 table name tablename = "product"; // 設定主 key pk = "p_id"; // 設定搜尋欄位 schfield = "p_name";

表單中需要加入 利用其與 javascript 溝通 <div> <input type="hidden" name=" EVENTTARGET" id=" EVENTTARGET" value="" /> <input type="hidden" name=" EVENTARGUMENT" id=" EVENTARGUMENT" value="" /> <script type="text/javascript"> //<![CDATA[ var theform = document.forms['form1']; if (!theform) { theform = document.form1; function dopostback(eventtarget, eventargument) { if (!theform.onsubmit (theform.onsubmit()!= false)) { theform. EVENTTARGET.value = eventtarget; theform. EVENTARGUMENT.value = eventargument; theform.submit(); //]]> </script> </div>

離線模式 protected void Page_Load(object sender, EventArgs e) { binddata("select * from customer"); private void binddata(string sql) { SqlConnection dbconn = new SqlConnection( 連線字串 "); dbconn.open(); DataSet ds = new DataSet(); SqlDataAdapter da = new SqlDataAdapter(sql, dbconn); da.fill(ds); GridView1.DataSource = ds; GridView1.DataBind(); dbconn.close();

ON-LINE MODE 異動資料

ExecuteNonQuery 透過以下三種 SQL 語法來修改資料庫資料 新增 :INSERT 修改 :UPDATE 刪除 :DELETE 透過 ExecuteNonQuery() 方法 回傳修改的資料筆數 用戶端 Command 資料庫引擎

異動資料程式結構 與查詢的程式結構一樣要使用 ExecuteNonQuery 方法 SqlCommand dbcmd = new SqlCommand( SQL 指令 ", dbconn); dbcmd.executenonquery(); 需要依照新 / 刪 / 修寫的 SQL 指令

動態 SQL 指令 1. 用假資料先寫出正確的 SQL 指令 2. 用程式取代假資料 3. 用雙引號將程式與原 SQL 指令切開 4. 用加號將切開位置串起來 把最後完成的結果貼回程式內的 Command 物件

動態 SQL 指令 1. 用假資料先寫出正確的 SQL 指令 Select * from customer where c_name like % 小 % 2. 用程式取代假資料 Select * from customer where c_name like %TextBox1.Text% 3. 用雙引號將程式與原 SQL 指令切開 Select * from customer where c_name like % TextBox1.Text % 4. 用加號將切開位置串起來 Select * from customer where c_name like % + TextBox1.Text + %

小練習 來將登入登出改成實際可用的 使用線上模式寫程式來達成! 讓欄位區分大小寫檢查 COLLATE Chinese_Taiwan_Stroke_CS_AI Select * from Users where u_account COLLATE Chinese_Taiwan_Stroke_CS_AI=@id and u_pwd COLLATE Chinese_Taiwan_Stroke_CS_AI=@pwd

改寫登入 String connstr = System.Web.Configuration.WebConfigurationManager.ConnectionStrings["POSConne ctionstring"].connectionstring.tostring(); SqlConnection dbconn = new SqlConnection(connstr); dbconn.open(); SqlCommand dbcmd = new SqlCommand("select * from customer where c_account=@c_account and c_pwd=@c_pwd", dbconn); dbcmd.parameters.addwithvalue("@c_account", TextBox1.Text); dbcmd.parameters.addwithvalue("@c_pwd", TextBox2.Text); SqlDataReader dbreader = dbcmd.executereader(); // 判斷帳號密碼 if(dbreader.read()){ // 改變 / 設定 session Session["iflogin"] = "1"; Session["loginuserid"] = dbreader[dbreader.getordinal("c_id")]; // 跳到設定畫面 Response.Redirect("NewBuycart.aspx"); dbconn.close(); else { Response.Write("<script>alert(' 帳號密碼錯誤 ');</script>"); dbconn.close();

SQL Injection 資料隱碼攻擊 SQL 指令的漏洞 or 1=1 or 1=1 or 1= ' or ''=' 取代有問題的字元 - / 等

避免 SQL Injection private string fixsql(string sql) { sql = sql.replace("'", ""); sql = sql.replace("\\", "//"); sql = sql.replace("-", "_"); sql = sql.replace("*", "_"); sql = sql.replace("+", "_"); return sql; 制輸入的長度降低 sql server 使用者權限至少不幸被入侵, 只是修改或刪除記錄而不會整個 database 被刪除

避免 SQL Injection 改用 ASP.NET 參數方式帶入 String UID = TextBox1.Text; String UPWD = TextBox2.Text; 參數 dbcmd.parameters.add("@id", SqlDbType.NVarChar).Value = fixsql(uid); dbcmd.parameters.add("@pwd", SqlDbType.NVarChar).Value = fixsql(upwd); SqlCommand dbcmd = new SqlCommand("Select * from Users where u_account COLLATE Chinese_Taiwan_Stroke_CS_AI=@id and u_pwd COLLATE Chinese_Taiwan_Stroke_CS_AI=@pwd and u_active=1", dbconn); 表示要區分大小寫

購物車結帳 // 產生單號 string news_id = System.DateTime.Now.ToString("yyyyMMddHHmmss"); String connstr = System.Web.Configuration.WebConfigurationManager.ConnectionStrings["POSConnectionString "].ConnectionString.ToString(); SqlConnection dbconn = new SqlConnection(connstr); dbconn.open(); // 建立主單 SqlCommand dbcmd = new SqlCommand("insert into sales (s_id,c_id,s_day,s_memo) values (@s_id,@c_id,@s_day,@s_memo)", dbconn); dbcmd.parameters.addwithvalue("@s_id", news_id); dbcmd.parameters.addwithvalue("@c_id", Session["loginuserid"].ToString()); dbcmd.parameters.addwithvalue("@s_day", System.DateTime.Now); dbcmd.parameters.addwithvalue("@s_memo", ""); dbcmd.executenonquery(); // 寫入明細 Cart = (DataTable)Session["ShoppingCart"]; foreach (DataRow objdr in Cart.Rows) { dbcmd = new SqlCommand("insert into sales_detail (s_id,p_id,amount,price) values (@s_id,@p_id,@amount,@price)", dbconn); dbcmd.parameters.addwithvalue("@s_id", news_id); dbcmd.parameters.addwithvalue("@p_id", objdr["itemid"]); dbcmd.parameters.addwithvalue("@amount", objdr["quantity"]); dbcmd.parameters.addwithvalue("@price", "123"); dbcmd.executenonquery(); dbconn.close(); Session["ShoppingCart"] = ""; Cart.Clear();

練習 1 製作一個註冊的表單 加入 Validation 檢查 必要輸入 帳號密碼不可以一樣 輸入長度檢查 ^[\s\s]{6,10$ 密碼強度 ( 大小寫至少 1, 混合數字, 長度 6~10) ^(?=.*\d)(?=.*[a-z])(?=.*[a-z]).{6,10$ Email 格式等