C# для профессионалов. Том II
Шрифт:
}
Это полный код примера всей транзакции, он показывает, как все части объединяются. Следующее просто встроено в библиотеку классов с заданным сильным именем и зарегистрировано в глобальном кэше сборок.
using System;
using System.EnterpriseServices;
using System.Data.SqlClient;
namespace OrderTransaction {
[Transaction(TransactionOptiоn.Required)]
public class Purchase : ServicedComponent {
public Purchase { }
public bool PlaceOrder(bool CommitTrans) {
//
Попытка работы
try {
if (CommitTrans) {
// Эта транзакция должна быть зафиксирована
// шаг 1 - Увеличить число единиц продукта ID=2 на 10
IncreaseUnits(2, 10);
// шаг 2 - Сократить запас продукта ID=2 на 10 единиц
ReduceStock(2, 10);
} else {
// Эта транзакция должна быть отменена
// шаг 3 — Увеличить число единиц продукта ID=5 на 5
IncreaseUnits(5, 5);
// шаг 2 — Сократить запас продукта ID=5 на 5
единиц ReduceStock(5, 5);
}
// Если все прошло хорошо, закончить транзакцию.
ContextUtil.SetComplete;
return true;
}
// Этот код выполняется, если встречается ошибка.
catch (Exception e) {
// Отменить работу, которую выполнила эта функция.
ContextUtil.SetAbort;
return false;
}
}
public void ReduceStock(int ProductID, int amount) {
string source = "server ephemeral;uid=sa;pwd=garysql;database Northwind";
SqlConnection conn = new SqlConnection(source);
string command =
"UPDATE Products SET UnitsInStock = UnitsInStock - " +
amount.ToString + " WHERE ProductID = " + ProductID.ToString;
conn.Open;
sqlCommand cmd = new SqlCommand(command, conn);
cmd.ExecuteNonQuery;
conn.Close;
}
public void IncreaseUnits(int ProductID, int amount) {
string source = "server=ephemeral;uid=sa;pwd=garysql;database=Northwind";
SqlConnection conn = new SqlConnection(source);
string command =
"UPDATE Products SET UnitsOnOrder = UnitsOnOrder +
" amount.ToString + " WHERE ProductID = " + ProductID.ToString;
conn.Open;
SqlCommand cmd = new SqlCommand(command, conn);
cmd.ExecuteNonQuery;
conn.Close;
}
public void Restore {
//
Восстановить запас продукта ID=2
ReduceStock(2, -10);
// Восстановить единицы продукта для ID=2
IncreaseUnits(2, -10);
// Не требуется восстанавливать запас или единицы продукта для ID=5,
// так так транзакция должна быть отменена
}
}
}
Можно создать клиента для тестирования этой библиотеки классов. Здесь клиент создан так, что он ожидает, пока пользователь проверит содержимое базы данных, прежде чем восстановить базу данных в исходное состояние. Это позволяет увидеть результаты транзакций.
statiс void Main(string[] args) {
Purchase order = new Purchase;
Console.WriteLine("\nThis transaction should commit");
Console.WriteLine("ProductID = 2, ordering 10 items");
if (Order.PlaceOrder(true)) Console.WriteLine("Transaction Successful");
else Console.WriteLine("Transaction Unsuccessful");
Console.WriteLine("\nThis transaction should roll back");
Console.WriteLine("ProductID = 5, ordering 5 items");
if (Order.PlaceOrder(false)) Console.WriteLine("Transaction Successful");
else Console.WriteLine("Transaction Unsuccessful");
Console.WriteLine(
"\nTake a look at the database then hit enter to
+ "return database to original state");
Console.ReadLine;
Order.Restore;
}
Другие полезные методы ContextUtil
Рассмотрим еще пару методов класса
ContextUtil
которые могут оказаться полезны при программировании на C#. Первый метод
IsCallerInRole
предназначен для безопасности на основе ролей. В качестве входной переменной этот метод получает строковую переменную, содержащую имя определенной роли системы безопасности Windows 2000. Он возвращает булево значение, указывающее, является или нет пользователь, который в данный момент вызывает объект, членом указанной роли. В примере кода ниже добавлена проверка, чтобы убедиться, что пользователь, пытающийся вызвать
PlaceOrder
, является авторизованным членом роли Administrators
. Если пользователь не является членом этой роли, то PlaceOrder
порождает исключение. [AutoComplete]
public bool PlaceOrder(bool CommitTrans) {
if (!ContextUtil.IsCallerInRole("Administrators") {
throw new AccessViolationException("User is not authorized to place" + "orders.");
Поделиться с друзьями: