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