Практическая работа по теме 9. "Особенности программирования в оконных операционных средах" Разработка приложения BankClient. Практическая работа посвящена построению приложения, в процессе создания которого мы воспользуемся большинством концепций, которые изучались в предыдущих темах. Оглавление Задание. Разработка приложения BankClient Цель Детальное рассмотрение особенностей создания программного приложения в оконных операционных средах. Решение Использовать все изученные ранее концепции, для разработки компонентов каждого из трех уровней в архитектуре приложения. Обсуждение На примере разработки приложения BankClient программирования в оконных операционных средах. рассмотрим особенности Создаваемое нами в качестве примера приложение BankClient предназначено для эмуляции работы профессионального банковского приложения. В окончательном варианте наше приложение должно будет уметь сверять баланс, устанавливать график выплат по счетам, модифицировать персональные профили, а также симулировать выполнение транзакций перечисления или снятия денег со счета клиента. На рис 9.1. показана логическая структура будущего приложения. Рис.9.1. Логика работы приложения, организованного в соответствии со стандартной трехуровневой архитектурой Для построения приложения используем стандартную трехуровневую архитектуру. Многоуровневая модель предполагает создание отдельных компонентов для пользовательского интерфейса (уровень представления Presentation Layer), для выполнения прикладной логики (промежуточный уровень - Middle Layer) и реализации базы данных (уровень данных - Data Layer) (рис.9.1). Уровни пользовательского интерфейса и базы данных представляют собой вполне понятные структуры - формы с элементами управления и таблицы базы данных соответственно, тогда как наполнение прикладной логики не так очевидно. В нашем случае для построения бизнес-логики приложения будут созданы четыре объекта. Первый из них, DataAccess, реализует функции взаимодействия базы данных с другими объектами. Объекты Bank, BillPay и Security отвечают за функциональную сторону прикладной логики. Использование подобной многоуровневой архитектуры гарантирует высокую гибкость, поскольку архитектура приложения базируется на объектной модели. Например, вы можете полностью поменять графический интерфейс пользователя, вообще не коснувшись объектов, реализующих функциональную логику приложения либо структуры базы данных. Еще одним преимуществом такой архитектуры являются широкие возможности масштабирования . Начнем поочередное создание каждого из трех уровней нашего приложения. Уровень данных - Data Layer 1. Средствами интегрированной студии MS Visual Studio .NET создайте базу данных BankClient под управлением MS SQL Server. 2. Добавьте в созданную базу таблицы, структура которых описана ниже. Таблица Account Таблица Customer Таблица Transactions Таблица Payee Таблица BillPay Таблица Login 3. Свяжите таблицы в соответствии с моделью данных, представленной на рис.9.2. 4. Напишите хранимую процедуру, необходимую для извлечения данных о клиентах . Код процедуры рассмотрен ниже. CREATE PROCEDURE GetCustomerInfo( @CustomerID int) AS SELECT * FROM Customer WHERE CustomerID=@CustomerID RETURN Рис.9.2. Модель данных приложения BankClient 5. Для внесения изменений в информацию о клиентах напишите хранимую процедуру, код которой приведен ниже. CREATE PROCEDURE UpdateCustomerInfo (@CustomerID int, @CustomerName nvarchar (50), @Address nvarchar (50), @City nvarchar (40), @Phone nvarchar (15)) AS UPDATE Customer SET CustomerName=@CustomerName, Address=@Address, City=@City, Phone=@Phone WHERE CustomerID=@CustomerID RETURN 6. Для просмотра сведений о счетах клиента создайте еще одну хранимую процедуру: CREATE PROCEDURE GetAccounts (@CustomerID int) AS SELECT AccountNumber, AccountType FROM Account WHERE CustomerID=@CustomerID RETURN 7. Для подсчета текущего баланса каждого клиента напишем хранимую процедуру: CREATE PROCEDURE GetAccountBalance (@Balance money OUT, @AccountNumber int) AS SELECT @Balance=SUM(Amount) FROM Transactions WHERE AccountNumber=@AccountNumber RETURN 8. Для реализации операции начисления и снятия денег со счета напишем следующую хранимую процедуру: CREATE PROCEDURE InsertTransaction (@TransactionType nvarchar (1), @AccountNumber int, @DestAccount int, @Amount money, @Comment nvarchar (255) ) AS INSERT INTO Transactions (TransactionType, AccountNumber, DestAccount, Amount, Comment, ModifyDate) VALUES (@TransactionType, @AccountNumber, @DestAccount, @Amount, @Comment, GetDate() ) RETURN 9. Получение сведений о транзакциях для определенного счета клиента опишем отдельной хранимой процедурой: CREATE PROCEDURE GetTransactions (@AccountNumber int) AS SELECT TransactionID, CONVERT (SMALLDATETIME, ModifyDate) AS TransactionDate, Comment, CASE WHEN TransactionType = 'D' THEN Amount ELSE NULL END AS credit, CASE WHEN TransactionType <>'D' THEN Amount ELSE NULL END AS debit FROM Transactions WHERE AccountNumber=@AccountNumber RETURN Обратите внимание, что в коде данной процедуры выполняется преобразование информации в столбце ModifyDate из типа DATETIME (дд/мм/гг чч:мм:сс) в тип SMALLDATETIME (дд/мм/гг), в результате чего будет возвращена только дата транзакции. Кроме того, мы создадим в процедуре два дополнительных столбца, с названием credit и debit. Они будут нужны нам только для раздельного вывода на экран информации о дебетовых и кредитовых операциях. Далее нам потребуются данные для осуществления выплат по счетам. Нам нужно будет выполнять добавление, обновление и удаление данных, для чего мы по очереди создадим три хранимых процедуры. 10. Напишем хранимую процедуру создания новых счетов, которые должны быть оплачены: CREATE PROCEDURE InsertBillPay (@AccountNumber int, @PayeeID int, @Amount money, @ScheduleDate datetime, @Period nvarchar (1)) AS INSERT INTO BillPay (AccountNumber, PayeeID, Amount, ScheduleDate, Period, ModifyDate) VALUES (@AccountNumber, @PayeeID, @Amount, @ScheduleDate, @Period, GetDate() ) RETURN 11. Для удаления счетов, представленных к оплате, будет использоваться уже другая процедура: CREATE PROCEDURE DeleteBillPay (@BillPayID int) AS DELETE FROM BillPay WHERE BillPayID=@BillPayID RETURN 12. Для модификации счета потребуется еще одна процедура: CREATE PROCEDURE UpdateBillPay (@BillPayID int, @AccountNumber int, @PayeeID int, @Amount money, @ScheduleDate datetime, @Period nvarchar(1)) AS UPDATE BillPay SET AccountNumber =@AccountNumber, PayeeID=@PayeeID, Amount=@Amount, ScheduleDate=@ScheduleDate, Period=@Period, ModifyDate=GetDate() WHERE BillPayID=@BillPayID RETURN Теперь, когда мы получили возможность создавать, изменять либо удалять информацию о выплатах по счетам, нам также необходимо организовать вывод на экран всей имеющейся информации по тому или иному счету. 13. Чтобы реализовать данную функцию, создадим дополнительную хранимую процедуру: CREATE PROCEDURE GetBillPay (@AccountNumber int) AS SELECT BillPayID, AccountNumber, BillPay.PayeeID, PayeeName, Amount, ScheduleDate, Period, CASE Period WHEN 'S' THEN 'Jne Time' WHEN 'M' THEN 'Monthly' WHEN 'Q' THEN 'Quarterly' WHEN 'Y' THEN 'Annually' END AS PerioDescription FROM BillPay INNER Join Payee ON BillPay.PayeeID=Payee.PayeeID WHERE AccountNumber=@AccountNumber RETURN 14. Теперь нам нужно создать список возможных Приступим к созданию очередной хранимой процедуры : CREATE PROCEDURE GetPayee получателей денег. AS SELECT PayeeID, PayeeName, Address, City, Phone FROM Payee ORDER BY PayeeName ASC RETURN Пользователи нашего приложения должны каким-то образом регистрироваться при входе на нашу web-страницу. Чтобы ограничить доступ к сайту, необходимо реализовать некоторую процедуру аутентификации пользователей, то есть проверку имени и пароля клиента. 15. Для проверки имени учетной записи и пароля мы создадим хранимую процедуру: CREATE PROCEDURE CheckPassword (@CustomerID int OUT, @UserID nvarchar (50), @Password nvarchar (20)) AS SELECT @CustomerID=CustomerID FROM Login WHERE UserID=@UserID AND Password=@Password RETURN 16. Нам также необходимо предоставить пользователю механизм изменения пароля. Для этого напишем процедуру: CREATE PROCEDURE UpdatePassword ( @CustomerID int, @Password nvarchar (20) ) AS UPDATE Login SET Password=@Password, ModifyDate=GetDate() WHERE CustomerID=@CustomerID RETURN Обратите внимание на использование функции GetDate() в данной процедуре. Функция нужна для получения информации о времени последнего запуска приложения пользователями, что позволяет выполнять простейший мониторинг пользователей . Средний уровень прикладной логики - Middle Layer - уровень После создания базы данных перейдем к проработке среднего (промежуточного) уровня нашего приложения. На этом уровне нам нужно создать объекты, реализующие прикладную (бизнес-) логику приложения: Объект DataAccess - обеспечивает нас функциями подключения и доступа к базе данных для выполнения разл ичных хранимых процедур; Объект Bank - с его помощью будет осуществляться управление информацией о пользователях и выполняемых ими транзакциях; Объект BillPay - будет использоваться для задания графика периодических выплат; Объект Security - управляет процессом аутентификации пользователей и предоставляет пользователям системы соответствующие полномочия. Объект DataAccess Класс DataAccess отвечает за функции подключения к базе данных и позволяет выполнить в ней различные хранимые процедуры. Это базовый класс, служащий основой для большинства проектов. Благодаря наличию данного класса, мы избавляем себя от необходимости ручного написания программного кода при обращении к объектам базы данных и в случае необходимости сможем даже изменить серверную часть нашей СУБД (например, перейти на Oracle). 1. Создайте новый проект Class Library под названием DBHelper. 2. Добавьте в проект новый класс с именем DataAccess.vb. Этот класс будет отвечать за доступ к базе данных. 3. Включите следующие операторы импортирования пространств имен: Imports System.Data.SqlClient, System.IO 4. Задайте константы, необходимые для идентификации объекта в журнале ошибок: Public Class DataAccess Private Const MODULE_NAME As String = "DBHelper" Private Const MODULE_SOURCE As String = "DataAccess" 5. Создайте переменные для хранения имени сервера и базы данных: Private m_sServer Private m_sDataBase As String As String 6. Опишите свойства класса DataAccess: Public Property Server() Get Return End Set(ByVal Value As m_sServer = End End Public Property DataBase() Get Return End Set(ByVal Value As m_sDataBase = End End Property As String m_sServer Get String) Value Set Property As String m_sDataBase Get String) Value Set 7. Создайте метод LogError для добавления сообщений об ошибках в журнал ошибок: Private Sub LogError(ByVal e As Exception) Dim LogMsg As StringWriter = New StringWriter LogMsg.WriteLine("Module: " & MODULE_SOURCE) LogMsg.WriteLine("Source: " & e.Source) LogMsg.WriteLine("Message: " & e.Message) LogMsg.WriteLine("Connect: " & GetConnectString()) System.Diagnostics.EventLog.WriteEntry(MODULE_NAME, LogMsg.ToString, Diagnostics.EventLogEntryType.Error) End Sub 8. Напишите частный (Private) метод, формирующий строку подключения к базе данных: Private Function GetConnectString() As String Dim myConnectStr As String = "Server=" & m_sServer & ";" & "Database=" & m_sDataBase & ";" & "User ID=sa; Password=;" Return myConnectStr End Function После создания подключения нам потребуется метод для реализации доступа к данным. Чтобы выполнить извлечение и обработку данных, необходимо создать объект SqlCommand. 9. Для этого напишем еще один частный (Private) метод, который и будет создавать объект SqlCommand и возвращать его нам: Private Function CreateCommand(ByVal SQLText As String, ByVal Param() As SqlParameter, ByVal SQLCmdType As CommandType) As SqlCommand Dim cnn As SqlConnection = New SqlConnection(GetConnectString()) Dim cmd As SqlCommand = New SqlCommand(SQLText, cnn) cmd.CommandType = SQLCmdType Dim ParamTemp As SqlParameter If Not Param Is Nothing Then For Each ParamTemp In Param cmd.Parameters.Add(ParamTemp) Next End If Try cnn.Open() Return cmd Catch ex As Exception LogError(e) Return Nothing End Try End Function Теперь создадим несколько открытых методов, которые будут использоваться другими объектами для получения доступа к базе данных. Запрограммируем три публичных (Public) метода под названием ExecuteSP с возможностью перегрузки. Перегрузка необходима для того, чтобы пользователь получал в результате обращения к одному и тому же методу в конечном итоге объект DataSet, DataReader либо пустой объект. 10. Напишите код метода ExecuteSP, возвращающего объект DataSet: Public Overloads Function ExecuteSP(ByVal SProcName As String, ByVal Param() As SqlParameter, ByVal MyDataSet As DataSet) As Boolean Dim cmd As SqlCommand = CreateCommand(SProcName, Param, CommandType.StoredProcedure) Dim da As SqlDataAdapter = New SqlDataAdapter(cmd) Try da.Fill(ds) Return True Catch ex As Exception LogError(e) Return False End Try End Function 11. Напишите код метода ExecuteSP, возвращающего пустой объект: Public Overloads Function ExecuteSP(ByVal SProcName As String, ByVal Param() As SqlParameter) As Boolean Dim cmd As SqlCommand = CreateCommand(SProcName, Param, CommandType.StoredProcedure) Try cmd.ExecuteNonQuery() Return True Catch ex As Exception LogError(e) Return False End Try End Function 12. Напишите код метода ExecuteSP, возвращающего объект DataReader: Public Overloads Function ExecuteSP(ByVal SProcName As String, ByVal Param() As SqlParameter, ByRef MyDataReader As SqlDataReader) As Boolean Dim cmd As SqlCommand = CreateCommand(SProcName, Param, CommandType.StoredProcedure) Try MyDataReader = cmd.ExecuteReader Return True Catch ex As Exception LogError(e) Return False End Try End Function 13. Откомпилируйте полученный объект DataAccess. Объект Bank Теперь начнем создавать новую библиотеку классов под названием IBank, которая будет содержать остальные необходимые нам объекты. 1. Создайте новый файл IBank.vb для хранения класса Bank. 2. Добавьте ссылки на пространство имен System.EnterpriseServices и только что скомпилированное пространство имен DBHelper. Ссылки на пространства имен можно сделать с помощью меню Project-Add Reference. Для включения в проект пространства имен DBHelper укажите путь к файлу DBHelper.dll с помощью кнопки Browser (рис.9.3) Рис.9.3. Добавление ссылок на пространства имен 3. Откройте класс Bank в редакторе кода и добавьте в самом начале два оператора Impotrs: Imports System.Data.SqlClient Imports System.EnterpriseServices 4. Задайте требование, в соответствии с которым в качестве префикса транзакции должно выступать имя нашего класса, так как наш класс наследуется от объекта System.EnterpriseServices.ServicedComponent, реализующего транзакционную фкнкциональность: < Transaction(TransactionOption.Required)> Class Inherits ServicedComponent Public Bank 5. Добавьте несколько закрытых констант, которые будут использованы для различия видов транзакций и для доступа к созданному ранее объекту DBHelper.DataAccess: Private Private Private Private Private Private Const TRANS_DEPOSIT As String = Const TRANS_WITHDRAW As String = Const TRANS_TRANSFER As String = Const TRANS_SERVICEFEE As String = Const TRANS_BILLPAY As String = m_objDataLayer As DBHelper.DataAccess "D" "W" "T" "S" "B" 6. Создайте конструктор класса Bank, который будет создавать новый экземпляра класса DBHelper.DataAccess для каждого нового объекта Bank: Public Sub New() 'Создадим новый объект DataAccess m_objDataLayer = New DBHelper.DataAccess 'Зададим настройки для нашей базы данных With m_objDataLayer .Server = "abrzh" .DataBase = "BankClient" End With End Sub Напишем два новых метода, позволяющих выполнять извлечение и обновление информации о пользователях. Для того чтобы извлечь либо обновить сведения об определенном клиенте, нам необходимо передать в соответствующий метод параметр CustomerID. Для получения данных о том, или ином клиенте мы будем использовать метод Bank.GetCustomerInfo, возвращая вызвавшему его коду объект SqlDataReader. При таком способе реализации в процессе извлечении информации не будет вовлечен объект DataSet. 7. Напишите код метода GetCustomerInfo: < AutoComplete()> Public Function GetCustomerInfo(ByVal CustomerID As Integer) As SqlDataReader Dim dr As SqlDataReader 'Создадим массив параметров Dim Param() As SqlParameter = {New SqlParameter("@CustomerID", SqlDbType.Int)} 'Передадим значение параметра Param(0).Value = CustomerID 'Извлечем информацию о данном клиенте Try If m_objDataLayer.ExecuteSP("GetCustomerInfo", Params, dr) = True Then Return dr Else Return Nothing End If Catch ex As Exception Return Nothing End Try End Function Задание префикса < AutoComplete()> включает автоматически использование транзакции вместе с подходящим методом SetComplete или SetAbort. 8. Создайте метод UpdateCustomerInfo. Поскольку с помощью этого метода мы собираемся модифицировать сведения о клиентах, нам необходимо определить параметры, при помощи которых будут вносить изменения в исходные данные: < AutoComplete()> Public Function UpdateCustomerInfo(ByVal CustomerID As Integer, ByVal CustomerName As String, ByVal Address As String, ByVal City As String, ByVal Phone As String) As Boolean 'Создадим массив параметров Dim Params() As SqlParameter = {New SqlParameter("@CustomerID", SqlDbType.Int), New SqlParameter("@CustomerName", SqlDbType.NVarChar, 50), New SqlParameter("@Address", SqlDbType.NVarChar, 50), New SqlParameter("@City", SqlDbType.NVarChar, 40), New SqlParameter("@Phone", SqlDbType.NVarChar, 30)} 'Свяжем значения переменных и параметров Params(0).Value = CustomerID Params(1).Value = CustomerName Params(2).Value = Address Params(3).Value = City Params(4).Value = Phone 'Сохраним информацию о клиенте Try Return m_objDataLayer.ExecuteSP("UpdateCustomerInfo", Params) Catch ex As Exception Return False End Try End Function 9. Определите методы, позволяющие работать с банковскими счетами наших клиентов: < AutoComplete()> Public Function GetAccounts(ByVal CustomerID As Integer) As SqlDataReader Dim dr As SqlDataReader 'Создадим массив параметров Dim Params() As SqlParameter = {New SqlParameter("@CustomerID", SqlDbType.Int)} 'Зададим значения параметров Params(0).Value = CustomerID Try If m_objDataLayer.ExecuteSP("GetAccounts", Params, dr) = True Then Return dr Else Return Nothing End If Catch ex As Exception Return Nothing End Try End Function < AutoComplete()> Public Function AccountBalance(ByVal AccountNumber As Integer) As Single Dim dr As SqlDataReader 'Создадим массив параметров Dim Params() As SqlParameter = {New SqlParameter("@Balance", SqlDbType.Real), New SqlParameter("@AccountNumber", SqlDbType.Int)} 'Зададим значения параметров Params(0).Direction = ParameterDirection.InputOutput Params(1).Value = AccountNumber Try If m_objDataLayer.ExecuteSP("GetAccountBalance", Params, dr) = True Then Return CSng(Params(0).Value) Else Return -1 End If Catch ex As Exception Return -1 End Try End Function 10. Создайте метод для получения списка транзакций по определенному счету. Метод будет возвращать объект DataSet, так как в пользовательском интерфейсе список транзакций будет выводиться в элементе управления DataGrid. < AutoComplete()> Public Function GetTransactions(ByVal AccountNumber As Integer) As DataSet Dim ds As New DataSet Dim Params() As SqlParameter = {New SqlParameter("@AccountNumber", SqlDbType.Int)} Params(0).Value = AccountNumber Try If m_objDataLayer.ExecuteSP("GetTransactions", Params, ds) = True Then Return ds Else Return Nothing End If Catch ex As Exception Return Nothing End Try End Function Для работы с транзакциями нам придется написать еще несколько методов. 11. Создайте закрытый метод для вставки информации о транзакциях в базу данных: < AutoComplete()> Private Function InsertTransaction(ByVal TransType As String, ByVal SourceAccount As Integer, ByVal DestAccount As Integer, ByVal Amount As Single, ByVal Comment As String) As Boolean Dim Params() As SqlParameter = {New SqlParameter("@TransactionType", SqlDbType.NVarChar, 6), _ New SqlParameter("@AccountNumber", SqlDbType.Int), _ New SqlParameter("@DestAccount", SqlDbType.Int), _ New SqlParameter("@Amount", SqlDbType.Real), _ New SqlParameter("@Comment", SqlDbType.NVarChar, 255)} Params(0).Value = TransType Params(1).Value = SourceAccount Params(2).Value = DestAccount Params(3).Value = Amount Params(4).Value = Comment Try Return m_objDataLayer.ExecuteSP("InsertTransaction", Params) Catch ex As Exception Return False End Try End Function Метод InsertTransaction может вызываться с помощью одного из четырех открытых методов. Эти четыре открытых метода представляют четыре поддерживаемые в нашей системе типа транзакций, а именно: депозиты, снятие денег со счета. Плата за обслуживание и перевод денег с одного счета на другой. 12. Рассмотрите как устроены открытые методы: < AutoComplete()> Public Function DepositFunds(ByVal AccountNumber As Integer, ByVal Amount As Single, ByVal Comment As String) As Boolean Try Return InsertTransaction(TRANS_DEPOSIT, AccountNumber, AccountNumber, Amount, Comment) Catch ex As Exception Return False End Try End Function < AutoComplete()> Public Function WithdrawFunds(ByVal AccountNumber As Integer, ByVal Amount As Single, ByVal Comment As String) As Boolean Try Return InsertTransaction(TRANS_WITHDRAW, AccountNumber, AccountNumber, Amount, Comment) Catch ex As Exception Return False End Try End Function < AutoComplete()> Public Function ApplyServiceFee(ByVal AccountNumber As Integer, ByVal Amount As Single, ByVal Comment As String) As Boolean Try Return InsertTransaction(TRANS_SERVICEFEE, AccountNumber, AccountNumber, Amount, Comment) Catch ex As Exception Return False End Try End Function < AutoComplete()> Public Function TransferFunds(ByVal SourceAccount As Integer, ByVal DestAccount As Integer, ByVal Amount As Single, ByVal Comment As String) As Boolean Try Return InsertTransaction(TRANS_TRANSFER, SourceAccount, DestAccount, Amount, Comment) Catch ex As Exception Return False End Try End Function Объект BillPay Объект BillPay предназначен для управления периодическими выплатами. Данный объект должен располагать средствами создания, обновления либо удаления расписаний выплат, а также средствами формирования других данных, используемых при создании графиков, например списка получателей. 1. Добавьте в проект новый файл класса с именем BillPay.vb. 2. Не забудьте импортировать нужные пространства имен: Imports System.EnterpriseServices, System.Data.SqlClient, System.Data Поскольку класс BillPay имеет структуру, аналогичную структуре класса Bank, дополнительных пояснений приводиться не будет. 3. Рассмотрите свойства и методы класса BillPay: < Transaction(TransactionOption.Required)> Public Class BillPay Private Const SCHEDULE_ONETIME As String = "S" Private Const SCHEDULE_MONTHLY As String = "M" Private Const SCHEDULE_QUARTERLY As String = "Q" Private Const SCHEDULE_ANNUALLY As String = "Y" Public Enum Schedule OneTime = 0 Monthly = 1 Quarterly = 2 Annually = 3 End Enum Private m_objDataLayer As DBHelper.DataAccess Public Sub New() m_objDataLayer = New DBHelper.DataAccess With m_objDataLayer .Server = "abrzh" .DataBase = "BankClient" End With End Sub Private Function GetPeriodCode(ByVal Period As Schedule) As String Select Case Period Case Schedule.OneTime Return SCHEDULE_ONETIME Case Schedule.Monthly Return SCHEDULE_MONTHLY Case Schedule.Quarterly Return SCHEDULE_QUARTERLY Case Schedule.Annually Return SCHEDULE_ANNUALLY End Select End Function < AutoComplete()> Public Function InsertBillPay(ByVal AccountNumber As Integer, ByVal PayeeID As Integer, ByVal Amount As Single, ByVal ScheduleDate As Date, ByVal Period As Schedule) As Boolean If IsDate(ScheduleDate) = False Then Return False Dim Params() As SqlParameter = {New SqlParameter("@AccountNumber", SqlDbType.Int), New SqlParameter("@PayeeID", SqlDbType.Int), New SqlParameter("@Amount", SqlDbType.Real), New SqlParameter("@ScheduleDate", SqlDbType.DateTime), New SqlParameter("@Period", SqlDbType.NVarChar, 6)} Params(0).Value = AccountNumber Params(1).Value = PayeeID Params(2).Value = Amount Params(3).Value = ScheduleDate Params(4).Value = GetPeriodCode(Period) Try Return m_objDataLayer.ExecuteSP("InsertBillPay", Params) Catch ex As Exception Return False End Try End Function < AutoComplete()> Public Function UpdateBillPay(byval BillPayId as Integer, ByVal AccountNumber As Integer, ByVal PayeeID As Integer, ByVal Amount As Single, ByVal ScheduleDate As Date, ByVal Period As Schedule) As Boolean Dim Params() As SqlParameter = {New SqlParameter("@BillPayID", SqlDbType.Int), New SqlParameter("@AccountNumber", SqlDbType.Int), New SqlParameter("@PayeeID", SqlDbType.Int), New SqlParameter("@Amount", SqlDbType.Real), New SqlParameter("@ScheduleDate", SqlDbType.DateTime), New SqlParameter("@Period", SqlDbType.NVarChar, 6)} Params(0).Value = BillPayId Params(1).Value = AccountNumber Params(2).Value = PayeeID Params(3).Value = Amount Params(4).Value = ScheduleDate Params(5).Value = GetPeriodCode(Period) Try Return m_objDataLayer.ExecuteSP("UpdateBillPay", Params) Catch ex As Exception Return False End Try End Function < AutoComplete()> Public Function DeleteBillPay(ByVal BillPayID As Integer) As Boolean Dim Params() As SqlParameter = {New SqlParameter("@BillPayID", SqlDbType.Int)} Params(0).Value = BillPayID Try Return m_objDataLayer.ExecuteSP("DeleteBillPay", Params) Catch ex As Exception Return False End Try End Function < AutoComplete()> Public Function GetBillPay(ByVal AccountNumber As Integer) As DataSet Dim ds As New DataSet Dim Params() As SqlParameter = {New SqlParameter("@AccountNumber", SqlDbType.Int)} Params(0).Value = AccountNumber Try If m_objDataLayer.ExecuteSP("GetBillPay", Params, ds) = True Then Return ds Else Return Nothing End If Catch ex As Exception Return Nothing End Try End Function < AutoComplete()> Public Function GetPayees() As SqlDataReader Dim dr As SqlDataReader Try If m_objDataLayer.ExecuteSP("GetPayee", Nothing, dr) = True Then Return dr Else Return Nothing End If Catch ex As Exception Return Nothing End Try End Function End Class Объект Security Объект Security отвечает не только за процесс аутентификации пользователей в системе, но и за выполнение операции по изменению паролей. 1. Добавьте в проект еще один файл класса с именем Security.vb. 2. Рассмотрите описание методов и свойств класса Security: Imports System.EnterpriseServices, System.Data.SqlClient < Transaction(TransactionOption.Required)> Public Class Security Private m_objDataLayer As DBHelper.DataAccess Public Sub New() m_objDataLayer = New DBHelper.DataAccess With m_objDataLayer .Server = "abrzh" .DataBase = "BankClient" End With End Sub < AutoComplete()> Public Function CheckCustomerPwd(ByVal UserID As String, ByVal Password As String) As Integer Dim Params() As SqlParameter = {New SqlParameter("@CustomerID", SqlDbType.Int), New SqlParameter("@UserID", SqlDbType.NVarChar, 50), New SqlParameter("@Password", SqlDbType.NVarChar, 20)} Params(0).Direction = System.Data.ParameterDirection.Output Params(1).Value = UserID Params(2).Value = password Try If m_objDataLayer.ExecuteSP("CheckPassword", Params) = True Then Return CInt(Params(0).Value) End If Catch ex As Exception Return 0 End Try End Function < AutoComplete()> Public Function UpdateCustomerPwd(ByVal CustomerID As String, ByVal Password As String) As Boolean Dim Params() As SqlParameter = {New SqlParameter("@CustomerID", SqlDbType.Int), New SqlParameter("@Password", SqlDbType.NVarChar, 20)} Params(0).Value = CustomerID Params(1).Value = Password Try Return m_objDataLayer.ExecuteSP("UpdatePassword", Params) Catch ex As Exception Return False End Try End Function End Class Теперь, когда мы завершили написание всех трех классов, необходимых для работы проекта, выполните компиляцию компонентов. Пользовательский интерфейс - Presentation Layer Для создания графического интерфейса пользователя воспользуемся комбинацией средств ASP.NET и VB.NET. ASP.NET предлагает множество элементов управления. Поделим нашу вэб-страницу на четыре логические части, ответственные за выполнение различных функций: обслуживание банковских автоматов (начисление денег на счет/снятие денег со счета), выплаты в соответствии с графиком, работу с профилями пользователей и выписки с банковского лицевого счета клиента. Каждая страница в составе приложения, за исключением входной страницы, должна иметь меню, с помощью которого пользователь будет получать доступ к другим частям системы. 1. Создайте вэб-приложение ASP.NET. Задайте имя новому проекту WBank. 2. Добавьте в новый проект ссылки на скомпилированный ранее файл IBank.dll с помощью диалога Add References и кнопки Browser в нем. 3. Включите в проект ссылку на пространство имен System.EnterpriseServices, как в предыдущих случаях. 4. Для настройки механизма аутентификации пользователей отредактируйте файл web.config. Удалите из него весь код, помещенный туда по умолчанию, и добавьте следующие строки: