原 SQL Server基礎(十) VS2015 連線資料庫——進階篇:資料庫事務
阿新 • • 發佈:2019-01-10
一、簡介
什麼是資料庫事務?假如一個數據有多個表,我們希望刪除A表的A1記錄,那麼B表就會對應地增加對應的B1記錄,從而保證資料的完整性與一致性。
比如:
參考:
二、往AutoLot新增一張CreditRisks表
CreditRisks表將記錄Customers表不誠信的使用者。
三、新增方法
類庫用上一篇部落格,新增方法ProcessCreditRisk即可。
/// <summary> /// 事務處理 /// </summary> /// <param name="throwEx"></param> /// <param name="custID"></param> public void ProcessCreditRisk(bool throwEx, int custID) { //根據使用者ID查詢不守信用的使用者名稱 string fName = string.Empty; string lName = string.Empty; SqlCommand cmdSelect = new SqlCommand( string.Format("Select * from Customers where CustID = {0}", custID), sqlConnection); using (SqlDataReader dr = cmdSelect.ExecuteReader()) { if (dr.HasRows) { dr.Read(); fName = (string)dr["FirstName"]; lName = (string)dr["LastName"]; } else return; } //建立刪除或新增的命令物件 SqlCommand cmdRemove = new SqlCommand( string.Format("Delete from Customers where CustID = {0}", custID), sqlConnection); SqlCommand cmdInsert = new SqlCommand(string.Format("Insert Into CreditRisks" + "(CustID, FirstName, LastName) Values" + "({0}, '{1}', '{2}')", custID, fName, lName), sqlConnection); // We will get this from the connection object. SqlTransaction tx = null; try { tx = sqlConnection.BeginTransaction(); // Enlist the commands into this transaction. cmdInsert.Transaction = tx; cmdRemove.Transaction = tx; // Execute the commands. cmdInsert.ExecuteNonQuery(); cmdRemove.ExecuteNonQuery(); // 模擬錯誤 if (throwEx) { throw new Exception("Sorry! Database error! Tx failed..."); } //提交事物 tx.Commit(); } catch (Exception ex) { Console.WriteLine(ex.Message); //有任何錯誤都會回滾事物。 tx.Rollback(); } }
四、C#工程
C#工程用上一篇部落格,新增 GetProcessCreditRisk方法即可
program.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using AutoLotConnectedLayer; //using System.Data; using System.Configuration; using System.Data; namespace AutoLotGUIclient { class Program { static void Main(string[] args) { string cnStr = ConfigurationManager.ConnectionStrings["AutoLotSqlProvider"].ConnectionString; bool userDone = false; string userCommand = ""; //建立InventoryDAL物件。 InventoryDAL invDAL = new InventoryDAL(); //開啟資料連線 invDAL.OpenConnection(cnStr); try { ShowInstructions(); do { Console.Write("\nPlease enter your command: "); //輸入指令 userCommand = Console.ReadLine(); Console.WriteLine("你剛才輸入的字母已經被轉為大寫:{0}", userCommand.ToUpper()); Console.WriteLine(); switch (userCommand.ToUpper()) { case "I": InsertNewCar(invDAL); break; case "U": UpdateCarPetName(invDAL); break; case "D": DeleteCar(invDAL); break; case "L": // ListInventory(invDAL); ListInventoryViaList(invDAL); break; case "S": ShowInstructions(); break; case "P": LookUpPetName(invDAL); break; case "TX": GetProcessCreditRisk(invDAL); break; case "Q": userDone = true; break; default: Console.WriteLine("Bad data! Try again"); break; } } while (!userDone); } catch (Exception ex) { Console.WriteLine(ex.Message); } finally { invDAL.CloseConnection(); } } #region Show instructions private static void ShowInstructions() { Console.WriteLine("I: Inserts a new car."); Console.WriteLine("U: Updates an existing car."); Console.WriteLine("D: Deletes an existing car."); Console.WriteLine("L: Lists current inventory."); Console.WriteLine("S: Shows these instructions."); Console.WriteLine("P: Looks up pet name."); Console.WriteLine("TX: 處理事物."); Console.WriteLine("Q: Quits program."); } #endregion #region List inventory private static void ListInventory(InventoryDAL invDAL) { // Get the list of inventory. DataTable dt = invDAL.GetAllInventoryAsDataTable(); DisplayTable(dt); } private static void ListInventoryViaList(InventoryDAL invDAL) { // Get the list of inventory. List<NewCar> record = invDAL.GetAllInventoryAsList(); foreach (NewCar c in record) { Console.WriteLine("CarID: {0}, Make: {1}, Color: {2}, PetName: {3}", c.CarID, c.Make, c.Color, c.PetName); } } private static void DisplayTable(DataTable dt) { // Print out the column names. for (int curCol = 0; curCol < dt.Columns.Count; curCol++) { Console.Write(dt.Columns[curCol].ColumnName + "\t"); } Console.WriteLine("\n----------------------------------"); // Print the DataTable. for (int curRow = 0; curRow < dt.Rows.Count; curRow++) { for (int curCol = 0; curCol < dt.Columns.Count; curCol++) { Console.Write(dt.Rows[curRow][curCol].ToString() + "\t"); } Console.WriteLine(); } } #endregion #region Delete car private static void DeleteCar(InventoryDAL invDAL) { // Get ID of car to delete. Console.Write("Enter ID of Car to delete: "); int id = int.Parse(Console.ReadLine()); // Just in case we have a primary key // violation! try { invDAL.DeleteCar(id); } catch (Exception ex) { Console.WriteLine(ex.Message); } } #endregion #region Insert car private static void InsertNewCar(InventoryDAL invDAL) { // First get the user data. int newCarID; string newCarColor, newCarMake, newCarPetName; Console.Write("Enter Car ID: "); newCarID = int.Parse(Console.ReadLine()); Console.Write("Enter Car Color: "); newCarColor = Console.ReadLine(); Console.Write("Enter Car Make: "); newCarMake = Console.ReadLine(); Console.Write("Enter Pet Name: "); newCarPetName = Console.ReadLine(); // Now pass to data access library. // invDAL.InsertAuto(newCarID, newCarColor, newCarMake, newCarPetName); NewCar c = new NewCar { CarID = newCarID, Color = newCarColor, Make = newCarMake, PetName = newCarPetName }; invDAL.InsertAuto(c); } #endregion #region Update pet name private static void UpdateCarPetName(InventoryDAL invDAL) { // First get the user data. int carID; string newCarPetName; Console.Write("Enter Car ID: "); carID = int.Parse(Console.ReadLine()); Console.Write("Enter New Pet Name: "); newCarPetName = Console.ReadLine(); // Now pass to data access library. invDAL.UpdateCarPetName(carID, newCarPetName); } #endregion #region Look up name private static void LookUpPetName(InventoryDAL invDAL) { // Get ID of car to look up. Console.Write("Enter ID of Car to look up: "); int id = int.Parse(Console.ReadLine()); Console.WriteLine("Petname of {0} is {1}.", id, invDAL.LookUpPetName(id).TrimEnd()); } #endregion public static void GetProcessCreditRisk(InventoryDAL invDAL) { //bool throwEx = true;//無法從表Customers刪除客戶3,且無法新增該使用者到表CreditRisks bool throwEx = false;//從表Customers刪除客戶3,且新增該使用者到表CreditRisks invDAL.ProcessCreditRisk(throwEx, 3); } } }
五、輸出結果
刪除Customers的第三行之前:
刪除中:
刪除後,Customers表少了一行,CreditRisks多了一行:
五、總結
至此,21章的學習,告一段落。