原 SQL Server基础(十) VS2015 连接数据库——进阶篇:数据库事务

一、简介

什么是数据库事务?假如一个数据有多个表,我们希望删除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章的学习,告一段落。

猜你喜欢

转载自blog.csdn.net/xpj8888/article/details/86150904