Чтение онлайн

ЖАНРЫ

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.");

Поделиться с друзьями: