本文介紹應用程式中添加書籍的保存功能,涉及兩個功能“新增”與“修改”。異常處理的小結。 ...
上接WCF學習之旅—第三個示例之一(二十七)
WCF學習之旅—第三個示例之二(二十八)
WCF學習之旅—第三個示例之四(三十)
十、添加保存功能
在此步驟中,將在應用程式中添加書籍的保存功能,涉及兩個功能“新增”與“修改”。
- 在解決方案資源管理器中,選中“FrmBook.cs”文件,在彈出的右鍵菜單中選擇“打開”,或者使用滑鼠左鍵雙擊。
- 在FrmBook.cs界面中,使用滑鼠雙擊“保存”按鈕與“清空”按鈕
- 然後在 btnSave _Click事件處理程式中添加以下代碼:
private void btnSave_Click(object sender, EventArgs e) { try { using (ChannelFactory<IBookService> channelFactory = new ChannelFactory<IBookService>("WSHttpBinding_IBookService")) { IBookService proxy = channelFactory.CreateChannel(); using (proxy as IDisposable) { if (string.IsNullOrEmpty(txtBookId.Text)) { textBoxMsg.Text = proxy.Add(GetBookInfo()); } else textBoxMsg.Text = proxy.Edit(GetBookInfo()); } } } catch (FaultException<SQLError> fex) { SQLError error = fex.Detail; textBoxMsg.Text = string.Format("拋出一個服務端錯誤。\r\n\t錯誤代碼:{0}\n\t錯誤原因:{1}\r\n\t操作:{2}\r\n\t錯誤信息:{3}\r\n\r\n", fex.Code, fex.Reason, error.Operation, error.ErrorMessage); } }
4. 在 buttonClear_Click事件處理程式中添加以下代碼
private void buttonClear_Click(object sender, EventArgs e) { txtBookId.Text = string.Empty; txtAuthorID.Text = string.Empty; textBoxName.Text = string.Empty; textBoxCategory.Text = string.Empty; textBoxPrice.Text = string.Empty; textBoxRating.Text = string.Empty; textBoxNumberofcopies.Text = string.Empty; txtPublishDate.Text = string.Empty; }
5.在菜單欄上,依次選擇“調試”和“啟動調試”以運行應用程式。
6. 在界面中使用滑鼠點擊“查詢”按鈕,顯示出全部的書籍記錄。
7. 使用滑鼠選中BookID=6的書籍信息,然後點擊“查詢選中的書籍”,這時會在“詳細信息”中顯示這本書的詳細信息。
8. 分別修改“價格”與“出版日期”,然後使用滑鼠點擊“保存”按鈕。
9.點擊“查詢”按鈕,再次查詢出結果,與之前的查詢結果進行比較。見下圖, “價格”與“出版日期”已經保存到資料庫。
10.接下來,我們來看看如何新增一條書籍信息。在“書籍信息”界面中,點擊“清空”按鈕,然後在詳細信息中分別輸入“作者編號”、“書名”、“類型”、“價格”、“評價”、“出版數量”、“出版日期”,點擊“保存”按鈕。就新增了一條新的記錄。如下圖。
十一、添加刪除功能
在此步驟中,將在應用程式中添加書籍的刪除功能。
- 在解決方案資源管理器中,選中“FrmBook.cs”文件,在彈出的右鍵菜單中選擇“打開”,或者使用滑鼠左鍵雙擊。
- 在FrmBook.cs界面中,使用滑鼠雙擊“刪除選中書籍”按鈕
- 然後在 btnDel _Click事件處理程式中添加以下代碼:
private void btnDel_Click(object sender, EventArgs e) { Books book = new Books(); if (gridBooks.SelectedRows.Count > 0) { book = gridBooks.SelectedRows[0].DataBoundItem as Books; textBoxMsg.Text = XMLHelper.ToXML<Books>(book); using (ChannelFactory<IBookService> channelFactory = new ChannelFactory<IBookService>("WSHttpBinding_IBookService")) { IBookService proxy = channelFactory.CreateChannel(); using (proxy as IDisposable) { textBoxMsg.Text = proxy.Delete(textBoxMsg.Text); } } } else { textBoxMsg.Text = "沒有選中相應的記錄!"; } }
4. 在菜單欄上,依次選擇“調試”和“啟動調試”以運行應用程式。
5. 在界面中使用滑鼠點擊“查詢”按鈕,顯示出全部的書籍記錄。
6. 使用滑鼠選中BookID=3的書籍信息,然後點擊“刪除選中書籍”。
7. 再次使用滑鼠點擊“查詢”按鈕,再次查詢出結果,與之前的查詢結果進行比較。見下圖, “BookID=3”的記錄已經被刪除了。
十二、關於異常處理的小結
1. 一開始,我對異常返回的寫法如下,在BookService.svc.cs文件,雙擊在“代碼編輯器”中打開,代碼如下,註意其中的“Edit”方法的異常返回,看上去沒什麼問題,但在具體實踐中,卻得到如圖1的錯誤,看得我摸不著頭腦,不知道錯在什麼地方。
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.Text; using BookMgr.Contracts; using BookMgr.Model; using BookMgr.Common; using System.Data.Entity; namespace BookMgr.Service { // 註意: 使用“重構”菜單上的“重命名”命令,可以同時更改代碼、svc 和配置文件中的類名“BookService”。 // 註意: 為了啟動 WCF 測試客戶端以測試此服務,請在解決方案資源管理器中選擇 BookService.svc 或 BookService.svc.cs,然後開始調試。 public class BookService :IBookService { BookEntities db = new BookEntities(); public string Add(string mbook) { try { Books book = XMLHelper.DeSerializer<Books>(mbook); db.Books.Add(book); db.SaveChanges(); } catch (Exception ex) { return ex.Message; } return "true"; } public string Delete(string bookInfo) { try { Books book = XMLHelper.DeSerializer<Books>(bookInfo); db.Entry(book).State = EntityState.Deleted; db.SaveChanges(); } catch (Exception ex) { return ex.Message; } return "true"; } public void DoWork() { } public string Edit(string mbook) { try { Books book = XMLHelper.DeSerializer<Books>(mbook); db.Entry(book).State = EntityState.Modified; db.SaveChanges(); } catch (Exception ex) { string reason = string.Empty; if (ex.InnerException != null) { reason = string.Format("{0}。InnerException:{1}",ex.Message, ex.InnerException.Message); } else reason = ex.Message; SQLError error = new SQLError("更新資料庫操作", reason); throw new FaultException<SQLError>(error, new FaultReason(reason), new FaultCode("Edit")); } return "true"; } public string Get(string Id) { int bookId = Convert.ToInt32(Id); Books book = db.Books.Find(bookId); string xml = XMLHelper.ToXML<Books>(book); return xml; //throw new NotImplementedException(); } public string Search(string Category, string searchString) { var cateLst = new List<string>(); var cateQry = from d in db.Books orderby d.Category select d.Category; cateLst.AddRange(cateQry.Distinct()); var books = from m in db.Books select m; if (!String.IsNullOrEmpty(searchString)) { books = books.Where(s => s.Name.Contains(searchString)); } List<Books> list = null; if (string.IsNullOrEmpty(Category)) { list = books.ToList<Books>(); //return XMLHelper.ToXML<List<Books>>(list); } else { list = books.Where(x => x.Category == Category).ToList<Books>(); // return XMLHelper.ToXML<IQueryable<Books>>(books.Where(x => x.Category == Category)); } return XMLHelper.ToXML<List<Books>>(list); } } }
2. 異常返回值圖。
圖1
3. 看來之前的寫法,無法獲取全部的異常信息,我添加了一個獲取異常的方法,把所有的內部異常信息獲取出來。具體代碼見下,下麵只有“Edit”方法的異常處理。
StringBuilder sb = new StringBuilder(); /// <summary> /// 遞歸獲取錯誤信息的內部錯誤信息,直到InnerException為null /// </summary> /// <param name="ex"></param> private string GetErrorMessage(Exception ex) { if (ex.InnerException != null) { sb.Append("InnerException:"+ex.Message + ","); GetErrorMessage(ex.InnerException); } else { sb.Append(ex.Message + ","); } return sb.ToString(); } public string Edit(string mbook) { try { Books book = XMLHelper.DeSerializer<Books>(mbook); db.Entry(book).State = EntityState.Modified; db.SaveChanges(); } catch (Exception ex) { string reason = GetErrorMessage(ex); SQLError error = new SQLError("更新資料庫操作", reason); throw new FaultException<SQLError>(error, new FaultReason(reason), new FaultCode("Edit")); } return "true"; }
4.這樣修改之後的異常返回,如下圖。這樣我們就能很容易知道問題出在哪裡了。