public static void Main() { Database.SetInitializer(new MigrateDatabaseToLatestVersion<AtmContext, AtmData.Migrations.Configuration>()); using (var atm = new AtmContext()) { FillInSampleRecords(atm); // Normal case Console.WriteLine(WithdrawMoney(atm, "1234567890", "1234", 500)); // Withdrawal of no money Console.WriteLine(WithdrawMoney(atm, "1234567890", "1234", 0)); // Wrong PIN Console.WriteLine(WithdrawMoney(atm, "1234567890", "0001", 500)); // Wrong card number Console.WriteLine(WithdrawMoney(atm, "4444444444", "1234", 500)); // Wrong card number and PIN Console.WriteLine(WithdrawMoney(atm, "4444444444", "4444", 500)); // Too much money Console.WriteLine(WithdrawMoney(atm, "1234567890", "1234", 5000)); Console.WriteLine(); Console.WriteLine("Transaction logs:"); foreach (var log in atm.TransactionLogs.Include("Account")) { Console.WriteLine("{0} | {1} | {2} | {3}", log.Id, log.Account.CardNumber, log.OldMoney, log.NewMoney); } } }
public static string WithdrawMoney(AtmContext atm, string cardNumber, string cardPin, decimal money) { var options = new TransactionOptions(); // Repeatable read - data can be added and read but not modified during a transaction options.IsolationLevel = IsolationLevel.RepeatableRead; using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, options)) { var card = atm.CardAccounts.Where(a => a.CardNumber == cardNumber && a.CardPin == cardPin).FirstOrDefault(); if (card == null) { return "The money withdrawal was unsuccessful. The card number or PIN is invalid."; } if (card.CardCash - money > 0) { decimal oldMoney = card.CardCash; card.CardCash -= money; decimal newMoney = card.CardCash; atm.SaveChanges(); transactionScope.Complete(); LogTransaction(atm, card, oldMoney, newMoney); return string.Format( "Successfully withdrew {0} dollars from card {1}. The amount remaining is {2}.", money, card.CardNumber.Substring(0, 4).PadRight(10, 'X'), card.CardCash); } else { return "The money withdrawal was unsuccessful. There are not enough money in the account."; } } }
private static void LogTransaction(AtmContext atm, CardAccount account, decimal oldMoney, decimal newMoney) { var options = new TransactionOptions(); // Snapshot - data can be read but before modifying the value is checked for updates options.IsolationLevel = IsolationLevel.RepeatableRead; using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, options)) { atm.TransactionLogs.Add(new TransactionLog() { Account = account, OldMoney = oldMoney, NewMoney = newMoney }); atm.SaveChanges(); transactionScope.Complete(); } }
private static void FillInSampleRecords(AtmContext atm) { atm.CardAccounts.Add(new CardAccount() { CardNumber = "1234567890", CardPin = "1234", CardCash = 2000 }); atm.CardAccounts.Add(new CardAccount() { CardNumber = "0452368874", CardPin = "4455", CardCash = 1000 }); atm.CardAccounts.Add(new CardAccount() { CardNumber = "8965123476", CardPin = "0000", CardCash = 500.23M }); atm.SaveChanges(); }