/// <summary>
        /// <see cref="Microsoft.Samples.NLayerApp.Application.MainModule.BankingManagement.IBankingManagementService"/>
        /// </summary>
        /// <param name="bankAccountNumber"><see cref="Microsoft.Samples.NLayerApp.Application.MainModule.BankingManagement.IBankingManagementService"/></param>
        /// <returns><see cref="Microsoft.Samples.NLayerApp.Application.MainModule.BankingManagement.IBankingManagementService"/></returns>
        public BankAccount FindBankAccountByNumber(string bankAccountNumber)
        {
            BankAccountNumberSpecification specification = new BankAccountNumberSpecification(bankAccountNumber);

            //query repository
            return(_bankAccountRepository.GetBySpec(specification as ISpecification <BankAccount>).SingleOrDefault());
        }
        /// <summary>
        /// <see cref="Microsoft.Samples.NLayerApp.Application.MainModule.BankingManagement.IBankingManagementService"/>
        /// </summary>
        /// <param name="fromAccountNumber"><see cref="Microsoft.Samples.NLayerApp.Application.MainModule.BankingManagement.IBankingManagementService"/></param>
        /// <param name="toAccountNumber"><see cref="Microsoft.Samples.NLayerApp.Application.MainModule.BankingManagement.IBankingManagementService"/></param>
        /// <param name="amount"><see cref="Microsoft.Samples.NLayerApp.Application.MainModule.BankingManagement.IBankingManagementService"/></param>
        public void PerformTransfer(string fromAccountNumber, string toAccountNumber, decimal amount)
        {
            //Process: 1º Start Transaction
            //         2º Get Accounts objects from Repositories
            //         3º Call PerformTransfer method in Domain Service
            //         4º If no exceptions, save changes using repositories and Commit Transaction

            //Create a transaction context for this operation
            TransactionOptions txSettings = new TransactionOptions()
            {
                Timeout        = TransactionManager.DefaultTimeout,
                IsolationLevel = IsolationLevel.Serializable // review this option
            };

            using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, txSettings))
            {
                //Get Unit of Work
                IUnitOfWork unitOfWork = _bankAccountRepository.UnitOfWork as IUnitOfWork;

                //Create Queries' Specifications
                BankAccountNumberSpecification originalAccountQuerySpec    = new BankAccountNumberSpecification(fromAccountNumber);
                BankAccountNumberSpecification destinationAccountQuerySpec = new BankAccountNumberSpecification(toAccountNumber);

                //Query Repositories to get accounts
                BankAccount originAccount = _bankAccountRepository.GetBySpec(originalAccountQuerySpec as ISpecification <BankAccount>)
                                            .SingleOrDefault();

                BankAccount destinationAccount = _bankAccountRepository.GetBySpec(destinationAccountQuerySpec as ISpecification <BankAccount>)
                                                 .SingleOrDefault();

                if (originAccount == null || destinationAccount == null)
                {
                    throw new InvalidOperationException(Resources.Messages.exception_InvalidAccountsForTransfer);
                }

                ////Start tracking STE entities (Self Tracking Entities)
                originAccount.StartTrackingAll();
                destinationAccount.StartTrackingAll();

                //Excute Domain Logic for the Transfer (In Domain Service)
                _bankTransferDomainService.PerformTransfer(originAccount, destinationAccount, amount);


                //Save changes and commit operations.
                //This opeation is problematic with concurrency.
                //"balance" property in bankAccount is configured
                //to FIXED in "WHERE concurrency checked predicates"

                _bankAccountRepository.Modify(originAccount);
                _bankAccountRepository.Modify(destinationAccount);

                //Complete changes in this Unit of Work
                unitOfWork.CommitAndRefreshChanges();

                //Commit the transaction
                scope.Complete();
            }
        }
        public void FindBankAccount_Invoke_InvalidCodeReturnNullObject_Test()
        {
            //Arrange
            IMainModuleUnitOfWork context      = this.GetUnitOfWork();
            ITraceManager         traceManager = this.GetTraceManager();
            BankAccountRepository repository   = new BankAccountRepository(context, traceManager);

            string invalidCode = "0200011111";
            BankAccountNumberSpecification spec = new BankAccountNumberSpecification(invalidCode);

            //Act
            BankAccount actual;

            actual = repository.GetBySpec(spec)
                     .SingleOrDefault();

            //Assert
            Assert.IsNull(actual);
        }
        public void FindBankAccount_Invoke_Test()
        {
            //Arrange
            IMainModuleUnitOfWork context      = this.GetUnitOfWork();
            ITraceManager         traceManager = this.GetTraceManager();
            BankAccountRepository repository   = new BankAccountRepository(context, traceManager);

            BankAccountNumberSpecification spec = new BankAccountNumberSpecification(bankAccountNumber);

            //Act
            BankAccount actual;

            actual = repository.GetBySpec(spec)
                     .SingleOrDefault();

            //Assert
            Assert.IsNotNull(actual);
            Assert.IsTrue(actual.BankAccountId == 1);
        }
        /// <summary>
        /// <see cref="Microsoft.Samples.NLayerApp.Application.MainModule.BankingManagement.IBankingManagementService"/>
        /// </summary>
        /// <param name="fromAccountNumber"><see cref="Microsoft.Samples.NLayerApp.Application.MainModule.BankingManagement.IBankingManagementService"/></param>
        /// <param name="toAccountNumber"><see cref="Microsoft.Samples.NLayerApp.Application.MainModule.BankingManagement.IBankingManagementService"/></param>
        /// <param name="amount"><see cref="Microsoft.Samples.NLayerApp.Application.MainModule.BankingManagement.IBankingManagementService"/></param>
        public void PerformTransfer(string fromAccountNumber, string toAccountNumber, decimal amount)
        {
            //Process: 1º Start Transaction
            //         2º Get Accounts objects from Repositories
            //         3º Call PerformTransfer method in Domain Service
            //         4º If no exceptions, save changes using repositories and Commit Transaction
            
            //Create a transaction context for this operation
            TransactionOptions txSettings = new TransactionOptions()
            {
                Timeout = TransactionManager.DefaultTimeout,
                IsolationLevel = IsolationLevel.Serializable // review this option
            };

            using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, txSettings))
            {
                //Get Unit of Work
                IUnitOfWork unitOfWork = _bankAccountRepository.UnitOfWork as IUnitOfWork;

                //Create Queries' Specifications
                BankAccountNumberSpecification originalAccountQuerySpec = new BankAccountNumberSpecification(fromAccountNumber);
                BankAccountNumberSpecification destinationAccountQuerySpec = new BankAccountNumberSpecification(toAccountNumber);

                //Query Repositories to get accounts
                BankAccount originAccount = _bankAccountRepository.GetBySpec(originalAccountQuerySpec as ISpecification<BankAccount>)
                                                                  .SingleOrDefault();

                BankAccount destinationAccount = _bankAccountRepository.GetBySpec(destinationAccountQuerySpec as ISpecification<BankAccount>)
                                                                  .SingleOrDefault();

                if (originAccount == null || destinationAccount == null)
                    throw new InvalidOperationException(Resources.Messages.exception_InvalidAccountsForTransfer);

                ////Start tracking STE entities (Self Tracking Entities)
                originAccount.StartTrackingAll();
                destinationAccount.StartTrackingAll();

                //Excute Domain Logic for the Transfer (In Domain Service) 
                _bankTransferDomainService.PerformTransfer(originAccount, destinationAccount, amount);


                //Save changes and commit operations. 
                //This opeation is problematic with concurrency.
                //"balance" property in bankAccount is configured 
                //to FIXED in "WHERE concurrency checked predicates"

                _bankAccountRepository.Modify(originAccount);
                _bankAccountRepository.Modify(destinationAccount);

                //Complete changes in this Unit of Work
                unitOfWork.CommitAndRefreshChanges();

                //Commit the transaction
                scope.Complete();
            }
        }
        /// <summary>
        /// <see cref="Microsoft.Samples.NLayerApp.Application.MainModule.BankingManagement.IBankingManagementService"/>
        /// </summary>
        /// <param name="bankAccountNumber"><see cref="Microsoft.Samples.NLayerApp.Application.MainModule.BankingManagement.IBankingManagementService"/></param>
        /// <returns><see cref="Microsoft.Samples.NLayerApp.Application.MainModule.BankingManagement.IBankingManagementService"/></returns>
        public BankAccount FindBankAccountByNumber(string bankAccountNumber)
        {
            BankAccountNumberSpecification specification = new BankAccountNumberSpecification(bankAccountNumber);

            //query repository
            return _bankAccountRepository.GetBySpec(specification as ISpecification<BankAccount>).SingleOrDefault();
        }