Enter the code for the following stored procedure: AS -- Declare local variables DECLARE @ID UNIQUEIDENTIFIER -- See if the ranking exists SELECT @ID = RoleID FROM Roles WHERE Ranking =
Trang 1The logic that you implement in the usp_UpdateRolestored procedure in the next Try It Out involvesthe use of IFstatements, variables, and the implementation of error handling You saw these SQL state-ments in action in the various INSERTstored procedures that you wrote in Chapter 11.
Try It Out Admin Form Stored Procedures
To complete this exercise:
1. Open your Time Tracker application in Visual Studio 2005
2. View the Server Explorer window and click the Auto Hide icon on the window to keep it visibleand then view the Stored Procedures node for your database
3. The first stored procedure to be created is the usp_UpdateRolestored procedure This storedprocedure updates a single role in the Roles table Readers using SQL Server should right-clickthe Stored Procedures and choose Add New Stored Procedure from the context menu Readersusing Oracle should use their favorite Oracle tool such as iSQL *Plus to create the stored proce-dures Enter the code for the following stored procedure:
AS
Declare local variables
DECLARE @ID UNIQUEIDENTIFIER
See if the ranking exists
SELECT @ID = RoleID FROM Roles WHERE Ranking = @Ranking
RAISERROR(‘Ranking already exists and cannot be duplicated.’,18,1)RETURN
ENDENDEND
Either the ranking does not exist or it belongs to the role being updated
BEGIN TRY
UPDATE RolesSet RoleName = @RoleName, RoleDescription = @RoleDescription, Ranking = @Ranking,
LastUpdateDate = GETDATE()WHERE RoleID = @RoleIDEND TRY
Trang 2BEGIN CATCHBEGINRAISERROR(‘Update role failed.’,18,1)RETURN
ENDEND CATCH
Click the Save icon on the toolbar to create the stored procedure
Oracle
CREATE OR REPLACE PROCEDURE usp_UpdateRole(
inRoleID CHAR,inRoleName VARCHAR2,inRoleDescription CLOB,inRanking NUMBER)
AS
Declare local variablesvarID CHAR(36);
BEGINBEGIN See if the ranking existsSELECT RoleID INTO varIDFROM Roles
WHERE Ranking = inRanking;
The ranking exists, now verify it doesn’t belong to the role you are updating
IF inRoleID <> varID THENRAISE_APPLICATION_ERROR (-20999,
‘Ranking already exists and cannot be duplicated.’);
RETURN;
END IF;
EXCEPTIONWHEN NO_DATA_FOUND THEN Handle the error but perform no processingNULL;
END;
BEGIN Either the ranking does not exist or it belongs to the role being updated
UPDATE RolesSet RoleName = inRoleName, RoleDescription = inRoleDescription, Ranking = inRanking,
LastUpdateDate = SYSDATEWHERE RoleID = inRoleID;
EXCEPTIONWHEN OTHERS THENRAISE_APPLICATION_ERROR( -20999,’Update role failed.’);
RETURN;
END;
END;
Trang 3Click the Execute button to have the stored procedure created in your database
4. The next stored procedure that you create is the usp_UpdateUserstored procedure, whichupdates a user in the Users table SQL Server users should right-click the Stored Proceduresnode in the Server Explorer and choose Add New Stored Procedure and Oracle users shoulduse their Oracle tool Enter the following code:
AS
Check to see if the password is blank
(no updates to the password)
IF LEN(@Password) = 0
BEGIN Get the current passwordSELECT @Password = PasswordFROM Users
WHERE UserID = @UserIDEND
Update the user
BEGIN TRY
UPDATE UsersSET LoginName = @LoginName, Password = @Password, FirstName = @FirstName, LastName = @LastName,Email = @Email, Phone = @Phone, Status = @Status, GroupID = @GroupID, RoleID = @RoleID, ManagerID = @ManagerID, LastUpdateDate = GETDATE()WHERE UserID = @UserIDEND TRY
BEGIN CATCH
BEGINRAISERROR(‘Update user failed.’,18,1)RETURN
ENDEND CATCH
Trang 4Click the Save icon on the toolbar to have the stored procedure created in your database
Oracle
CREATE OR REPLACE PROCEDURE usp_UpdateUser(
inUserID CHAR,inLoginName VARCHAR2,inPassword VARCHAR2,inFirstName VARCHAR2,inLastName VARCHAR2,inEmail VARCHAR2,inPhone VARCHAR2,inStatus NUMBER,inGroupID CHAR,inRoleID CHAR,inManagerID CHAR)
AS
Declare local variablesvarPassword VARCHAR2(30);
BEGINBEGIN Check to see if the password is null (no updates to the password)
IF inPassword IS NULL THEN Get the current passwordSELECT Password INTO varPasswordFROM Users
WHERE UserID = inUserID;
ELSEvarPassword := inPassword;
END IF;
END;
BEGIN Update the userUPDATE UsersSET LoginName = inLoginName, Password = varPassword, FirstName = inFirstName, LastName = inLastName,Email = inEmail, Phone = inPhone, Status = inStatus, GroupID = inGroupID, RoleID = inRoleID, ManagerID = inManagerID,LastUpdateDate = SYSDATEWHERE UserID = inUserID;
EXCEPTIONWHEN OTHERS THENRAISE_APPLICATION_ERROR (-20999,’Update Users failed.’);
Trang 5END;
END;
Click the Execute button to have the stored procedure created in your database
5. Add some code to your data access component to execute these stored procedures Starting withthe WDARolesclass, you add a function to update a role Add the UpdateRolefunction to thisclass:
SqlDbType.VarChar, 50, _Role.Tables(“Role”).Rows(0).Item(“RoleName”))MyBase.AddParameter(“@RoleDescription”, _SqlDbType.Text, _
Role.Tables(“Role”).Rows(0).Item( _
“RoleDescription”).ToString.Length, _Role.Tables(“Role”).Rows(0).Item(“RoleDescription”))MyBase.AddParameter(“@Ranking”, _
SqlDbType.TinyInt, 1, _Role.Tables(“Role”).Rows(0).Item(“Ranking”))
‘Execute the stored procedureUpdateRole = ExecuteStoredProcedure()Catch ExceptionErr As Exception
Throw New System.Exception(ExceptionErr.Message, _ExceptionErr.InnerException)
End TryEnd Function
OracleClient.OracleType.VarChar, 50, _Role.Tables(“Role”).Rows(0).Item(“RoleName”))MyBase.AddParameter(“inRoleDescription”, _OracleClient.OracleType.Clob, _
Role.Tables(“Role”).Rows(0).Item( _
Trang 6“RoleDescription”).ToString.Length, _Role.Tables(“Role”).Rows(0).Item(“RoleDescription”))MyBase.AddParameter(“inRanking”, _
OracleClient.OracleType.Number, 1, _Role.Tables(“Role”).Rows(0).Item(“Ranking”))
‘Execute the stored procedureUpdateRole = ExecuteStoredProcedure()Catch ExceptionErr As Exception
Throw New System.Exception(ExceptionErr.Message, _ExceptionErr.InnerException)
End TryEnd Function
6. Add the UpdateUserfunction, which is in the WDAUsersclass View the code for that class andadd the following function:
SqlDbType.VarChar, 15, _User.Tables(“User”).Rows(0).Item(“LoginName”))MyBase.AddParameter(“@Password”, _
SqlDbType.VarChar, 30, _User.Tables(“User”).Rows(0).Item(“Password”))MyBase.AddParameter(“@FirstName”, _
SqlDbType.VarChar, 30, _User.Tables(“User”).Rows(0).Item(“FirstName”))MyBase.AddParameter(“@LastName”, _
SqlDbType.VarChar, 30, _User.Tables(“User”).Rows(0).Item(“LastName”))MyBase.AddParameter(“@Email”, _
SqlDbType.VarChar, 50, _User.Tables(“User”).Rows(0).Item(“Email”))MyBase.AddParameter(“@Phone”, _
SqlDbType.VarChar, 20, _User.Tables(“User”).Rows(0).Item(“Phone”))MyBase.AddParameter(“@Status”, _
SqlDbType.Bit, 1, _User.Tables(“User”).Rows(0).Item(“Status”))MyBase.AddParameter(“@GroupID”, _
SqlDbType.UniqueIdentifier, 16, _User.Tables(“User”).Rows(0).Item(“GroupID”))MyBase.AddParameter(“@RoleID”, _
SqlDbType.UniqueIdentifier, 16, _User.Tables(“User”).Rows(0).Item(“RoleID”))MyBase.AddParameter(“@ManagerID”, _
SqlDbType.UniqueIdentifier, 16, _User.Tables(“User”).Rows(0).Item(“ManagerID”))
Trang 7‘Execute the stored procedureUpdateUser = ExecuteStoredProcedure()Catch ExceptionErr As Exception
Throw New System.Exception(ExceptionErr.Message, _ExceptionErr.InnerException)
End TryEnd Function
OracleClient.OracleType.VarChar, 15, _User.Tables(“User”).Rows(0).Item(“LoginName”))MyBase.AddParameter(“inPassword”, _
OracleClient.OracleType.VarChar, 30, _User.Tables(“User”).Rows(0).Item(“Password”))MyBase.AddParameter(“inFirstName”, _
OracleClient.OracleType.VarChar, 30, _User.Tables(“User”).Rows(0).Item(“FirstName”))MyBase.AddParameter(“inLastName”, _
OracleClient.OracleType.VarChar, 30, _User.Tables(“User”).Rows(0).Item(“LastName”))MyBase.AddParameter(“inEmail”, _
OracleClient.OracleType.VarChar, 50, _User.Tables(“User”).Rows(0).Item(“Email”))MyBase.AddParameter(“inPhone”, _
OracleClient.OracleType.VarChar, 20, _User.Tables(“User”).Rows(0).Item(“Phone”))MyBase.AddParameter(“inStatus”, _
OracleClient.OracleType.Number, 1, _User.Tables(“User”).Rows(0).Item(“Status”))MyBase.AddParameter(“inGroupID”, _
OracleClient.OracleType.Char, 36, _User.Tables(“User”).Rows(0).Item(“GroupID”).ToString)MyBase.AddParameter(“inRoleID”, _
OracleClient.OracleType.Char, 36, _User.Tables(“User”).Rows(0).Item(“RoleID”).ToString)MyBase.AddParameter(“inManagerID”, _
OracleClient.OracleType.Char, 36, _User.Tables(“User”).Rows(0).Item(“ManagerID”).ToString)
‘Execute the stored procedureUpdateUser = ExecuteStoredProcedure()Catch ExceptionErr As Exception
Throw New System.Exception(ExceptionErr.Message, _ExceptionErr.InnerException)
End TryEnd Function
Trang 87. Now you add code in your business logic component to support the functions just added inyour data access component View the code for the WBLRolesclass and add the following func-tion to update a role:
Public Function UpdateRole(ByVal Role As DataSet) As BooleanTry
‘Validate role dataValidateRoleData(Role)
‘Call the data component to update the roleReturn objWDARoles.UpdateRole(Role)
Catch ExceptionErr As ExceptionThrow New System.Exception(ExceptionErr.Message, _ExceptionErr.InnerException)
End TryEnd Function
8. Now view the code for the WBLUsersclass and add the UpdateUserfunction:
Public Function UpdateUser(ByVal User As DataSet) As BooleanTry
‘Validate the Login Name exists
If User.Tables(“User”).Rows(0).Item( _
“LoginName”).ToString.Trim.Length = 0 ThenThrow New System.Exception(“Login Name is a required field.”)End If
‘Validate the First Name exists
If User.Tables(“User”).Rows(0).Item( _
“FirstName”).ToString.Trim.Length = 0 ThenThrow New System.Exception(“First Name is a required field.”)End If
‘Validate the Last Name exists
If User.Tables(“User”).Rows(0).Item( _
“LastName”).ToString.Trim.Length = 0 ThenThrow New System.Exception(“Last Name is a required field.”)End If
‘Validate the password
If User.Tables(“User”).Rows(0).Item( _
“Password”).ToString.Trim.Length = 0 Then
‘The old password is not being updated so set it to NullUser.Tables(“User”).Rows(0).Item(“Password”) = DBNull.ValueElse
‘A new password has been supplied
If Not IsValidPassword(User.Tables( _
“User”).Rows(0).Item(“Password”)) ThenThrow New System.Exception(strErrorMessage)Else
‘Hash the passwordUser.Tables(“User”).Rows(0).Item(“Password”) = _HashPassword(User.Tables(“User”).Rows(0).Item( _
“Password”))End If
Trang 9End If
‘Validate the email
If Not IsValidEmail(User.Tables( _
“User”).Rows(0).Item(“Email”)) ThenThrow New System.Exception(strErrorMessage)End If
‘Validate the phone number
If Not IsValidPhoneNumber(User.Tables( _
“User”).Rows(0).Item(“Phone”)) ThenThrow New System.Exception(strErrorMessage)End If
‘Validate manager
If Not IsDBNull(User.Tables(“User”).Rows(0).Item(“ManagerID”)) Then
If Not TypeOf User.Tables(“User”).Rows(0).Item(“ManagerID”) _
Is Guid Then
If User.Tables(“User”).Rows(0).Item(“ManagerID”) = _String.Empty Then
‘Set it to a null valueUser.Tables(“User”).Rows(0).Item(“ManagerID”) = _DBNull.Value
End IfEnd IfEnd If
‘Trim spacesUser.Tables(“User”).Rows(0).Item(“LoginName”) = _User.Tables(“User”).Rows(0).Item(“LoginName”).ToString.TrimUser.Tables(“User”).Rows(0).Item(“Password”) = _
User.Tables(“User”).Rows(0).Item(“Password”).ToString.TrimUser.Tables(“User”).Rows(0).Item(“FirstName”) = _
User.Tables(“User”).Rows(0).Item(“FirstName”).ToString.TrimUser.Tables(“User”).Rows(0).Item(“LastName”) = _
User.Tables(“User”).Rows(0).Item(“LastName”).ToString.TrimUser.Tables(“User”).Rows(0).Item(“Email”) = _
User.Tables(“User”).Rows(0).Item(“Email”).ToString.Trim
‘Format the phone numberUser.Tables(“User”).Rows(0).Item(“Phone”) = _FormatPhoneNumber(User.Tables(“User”).Rows(0).Item(“Phone”))
‘Call the data component to update the userReturn objWDAUsers.UpdateUser(User)
Catch ExceptionErr As ExceptionThrow New System.Exception(ExceptionErr.Message, _ExceptionErr.InnerException)
End TryEnd Function
9. Switch to the code in the Admin form and update it to execute the functions you added in yourbusiness logic component View the code for the ActionUpdateprocedure and add the follow-ing code under the Case “Roles”statement:
Trang 10Case “Roles”
‘Initialize a new instance of the business logic componentUsing objRoles As New WroxBusinessLogic.WBLRoles( _strCompany, strApplication)
‘Get a new Role DataSetobjDataSet = objRoles.GetNewRoleDS()
‘Initialize a datarow object from the Role DataSetDim objDataRow As Data.DataRow = _
objDataSet.Tables(“Role”).NewRow
‘Set the values in the DataRowobjDataRow.Item(“RoleID”) = New Guid(txtRoleID.Text)objDataRow.Item(“RoleName”) = txtRoleName.TextobjDataRow.Item(“RoleDescription”) = _
txtRoleDescription.TextobjDataRow.Item(“Ranking”) = _CType(txtRanking.Text, Byte)
‘Add the DataRow to the DataSetobjDataSet.Tables(“Role”).Rows.Add(objDataRow)
‘Update the Role in the database
If Not objRoles.UpdateRole(objDataSet) ThenThrow New Exception(“Update Role Failed”)End If
End Using
‘Clear the input fieldstxtRoleID.Text = String.EmptytxtRoleName.Text = String.EmptytxtRoleDescription.Text = String.EmptytxtRanking.Text = String.Empty
‘Get a new User DataSetobjDataSet = objUsers.GetNewUserDS()
‘Initialize a datarow object from the Role DataSetDim objDataRow As Data.DataRow = _
objDataSet.Tables(“User”).NewRow
‘Set the values in the DataRowobjDataRow.Item(“UserID”) = New Guid(txtUserID.Text)objDataRow.Item(“LoginName”) = txtLogin.Text
objDataRow.Item(“Password”) = txtPassword.TextobjDataRow.Item(“FirstName”) = txtFirstName.TextobjDataRow.Item(“LastName”) = txtLastName.TextobjDataRow.Item(“Email”) = txtEmail.TextobjDataRow.Item(“Phone”) = txtPhone.TextobjDataRow.Item(“Status”) = optStatusActive.Checked
Trang 11objDataRow.Item(“GroupID”) = _cboUserGroup.SelectedItem.Item(“GroupID”)objDataRow.Item(“RoleID”) = _
cboUserRole.SelectedItem.Item(“RoleID”)
If cboUserManager.SelectedIndex <> -1 ThenobjDataRow.Item(“ManagerID”) = _cboUserManager.SelectedItem.item(“ManagerID”)End If
‘Add the DataRow to the DataSetobjDataSet.Tables(“User”).Rows.Add(objDataRow)
‘Update the User in the database
If Not objUsers.UpdateUser(objDataSet) ThenThrow New Exception(“Update User Failed”)End If
End Using
‘Clear the input fieldstxtUserID.Text = String.EmptytxtLogin.Text = String.EmptytxtPassword.Text = String.EmptytxtFirstName.Text = String.EmptytxtLastName.Text = String.EmptytxtEmail.Text = String.EmptytxtPhone.Text = String.EmptyoptStatusActive.Checked = TruetxtUserUpdateDate.Text = String.Empty
‘Reload the Managers combo boxCall LoadManagers()
‘Reload the Users listCall LoadUsers()cboUserGroup.SelectedIndex = -1cboUserRole.SelectedIndex = -1cboUserManager.SelectedIndex = -1
To test these changes, start your project When the Login form is displayed, enter the admin user andpassword that you created in your database When the Admin form is displayed, navigate to the Rolesscreen
Click a role and change the ranking for that role to one that is not used Then click the Update button onthe toolbar or click the Action menu and select Update The role will be updated as shown in Figure 13-1.Click the same role again and update the ranking to one being used by one of the other roles When you attempt to update the role in the database, you receive a message dialog box informing you that theranking already exists and cannot be duplicated The role will not be updated and the information dis-played in the details section of the screen remains, enabling you to correct the problem and try again
Trang 13How It Works
The first stored procedure you create in this exercise is the usp_UpdateRolestored procedure Thisstored procedure checks the Roles table for an existing ranking equal to the one passed to this storedprocedure It then compares the RoleID of that ranking, if found, against the RoleID being passed to this stored procedure to determine whether the ranking belongs to the role being updated If the ranking does not belong to the role being updated, an error is raised and the update is cancelled.Because the Oracle version of this stored procedure differs slightly from the SQL Server version, Iexplain both versions, starting with the SQL Server version
The first part of this stored procedure defines the stored procedure name and its input parameters This
is all standard stuff that you’ve seen time and again
AS
You need to retrieve the RoleID from the Roles table if an existing ranking is found that matches theranking passed to this stored procedure This enables you to compare the RoleID in the Roles tableagainst the RoleID passed as input to this stored procedure To that end, you must declare a local vari-able in your stored procedure for the RoleID, which is what has been done in the next line of code.Next, you set the @IDvariable by selecting the RoleID into it where the Ranking column contains thesame ranking as the @Rankinginput parameter Next, you check the @IDvariable to see if it is not null
in the IFstatement that follows the SELECTstatement This determines whether a row of data wasselected
If the @IDvariable is not null, a row of data exists in the Roles table with the same ranking as the onepassed to this stored procedure You want to determine whether the RoleID that was set in the @IDvari-able is not equal to the RoleID passed in the @RoleIDinput parameter If the values are not equal, youraise an error that the ranking already exists and exit the stored procedure via the RETURNstatement. Declare local variables
DECLARE @ID UNIQUEIDENTIFIER
See if the ranking exists
SELECT @ID = RoleID FROM Roles WHERE Ranking = @Ranking
Trang 14RAISERROR(‘Ranking already exists and cannot be duplicated.’,18,1)RETURN
ENDENDEND
If you’ve gotten this far, the ranking does not already exist or it belongs to the role being updated.Therefore, you proceed with the UPDATEstatement to update the role If an error occurred during theprocessing of the UPDATEstatement, control will be passed to your BEGIN CATCH END CATCHblockwhere you raise an error that the update failed
Either the ranking does not exist or it belongs to the role being updatedBEGIN TRY
UPDATE RolesSet RoleName = @RoleName, RoleDescription = @RoleDescription, Ranking = @Ranking,
LastUpdateDate = GETDATE()WHERE RoleID = @RoleIDEND TRY
BEGIN CATCHBEGINRAISERROR(‘Update role failed.’,18,1)RETURN
ENDEND CATCH
The Oracle version of this stored procedure starts the same as the SQL Server version You define thestored procedure name and its input parameters
OracleCREATE OR REPLACE PROCEDURE usp_UpdateRole(
inRoleID CHAR,inRoleName VARCHAR2,inRoleDescription CLOB,inRanking NUMBER)
AS
You also need to declare a local variable to hold the RoleID that will be selected from the Roles table, andthat it done in the next statement Then you begin the stored procedure with the BEGIN ENDblockand you have two separate blocks of logic: both are enclosed in a BEGIN ENDblock
You select the RoleID into the varIDlocal variable where the Ranking column in the Roles table matchesthe value in the inRankinginput parameter Oracle throws an exception if no data is found so you havecode to handle that exception Immediately following the SELECTstatement you compare the RoleID inthe inRoleIDinput parameter against the RoleID in the varIDvariable to see if they are not equal Ifthey are not equal, you raise an error that the ranking already exists and exit the stored procedure viathe RETURNstatement
Trang 15If the NO_DATA_FOUNDexception was thrown, you know that the ranking did not already exist and you
do not want to do anything However, you have to have the code in your stored procedure to handle theNO_DATA_FOUNDexception and you must include some code in that block Because you do not want to
do anything, you specify a NULLstatement, which satisfies Oracle’s compiler that the NO_DATA_FOUNDexception block contains some code
Declare local variables
varID CHAR(36);
BEGIN
BEGIN See if the ranking existsSELECT RoleID INTO varIDFROM Roles
WHERE Ranking = inRanking;
The ranking exists, now verify it doesn’t belong to the role you are updating
IF inRoleID <> varID THENRAISE_APPLICATION_ERROR (-20999,
‘Ranking already exists and cannot be duplicated.’);
RETURN;
END IF;
EXCEPTIONWHEN NO_DATA_FOUND THEN Handle the error but perform no processingNULL;
END;
At this point, you know that the ranking did not already exist or that it belongs to the role being updated.Now you can update the role in the Roles table using the following UPDATEstatement You’ve includedthe appropriate error handling to handle any errors that may occur from the UPDATEstatement
BEGIN Either the ranking does not exist or it belongs to the role being updated
UPDATE RolesSet RoleName = inRoleName, RoleDescription = inRoleDescription, Ranking = inRanking,
LastUpdateDate = SYSDATEWHERE RoleID = inRoleID;
EXCEPTIONWHEN OTHERS THENRAISE_APPLICATION_ERROR( -20999,’Update role failed.’);
RETURN;
END;
END;
The next stored procedure you create is the usp_UpdateUserstored procedure This stored procedure
is a fairly simple UPDATEstored procedure that you’ve seen before; therefore, the entire code will not belisted again The one thing that is different about this stored procedure is that it checks to see whether apassword has been passed to this stored procedure
Trang 16The SQL Server version of this stored procedure checks the length of the @Passwordinput parameterusing the LENfunction This function returns the number of characters in the expression being evalu-ated If the length of the @Passwordinput parameter is equal to zero, you select the current user’s pass-word into this parameter, which will be used in the UPDATEstatement.
Check to see if the password is blank (no updates to the password)
IF LEN(@Password) = 0BEGIN
Get the current passwordSELECT @Password = PasswordFROM Users
WHERE UserID = @UserIDEND
The Oracle version of this stored procedure requires that you declare a local variable first as you cannotalter the contents of the input parameters to the stored procedure Then you check to see whether theinPasswordparameter is null by using the IS NULLstatement If it is null, you select the user’s currentpassword into the varPasswordvariable; otherwise you set the password in the inPasswordparameter
in the varPasswordvariable This variable will then be used in your UPDATEstatement to update theuser’s password
Declare local variablesvarPassword VARCHAR2(30);
BEGINBEGIN Check to see if the password is null (no updates to the password)
IF inPassword IS NULL THEN Get the current passwordSELECT Password INTO varPasswordFROM Users
WHERE UserID = inUserID;
ELSEvarPassword := inPassword;
END IF;
END;
You add the UpdateRolefunction to the WDARolesclass in the data access component next The SQLServer version of this function is listed next in this section and the only differences between the SQLServer and Oracle versions are the data types used in the Parameterscollection
You encapsulate the code in this function in a Try Catchblock to handle any errors that may bethrown from the execution of the usp_UpdateRolestored procedure The first thing that you do in theTryblock is set the SQLproperty in the base class to the stored procedure being executed Then you callthe InitializeCommandmethod in the base class to initialize the Commandobject You then proceed byadding the appropriate parameters to the Parameterscollection, passing the values for the parametersusing the data from the Role DataSetthat was passed as input to this function Finally, you execute thestored procedure by calling the ExecuteStoredProceduremethod in the base class
Trang 17The Catchblock contains the appropriate error-handling code to throw a new exception back to thecaller of this function, passing it the exception that this function received.
Public Function UpdateRole(ByVal Role As DataSet) As BooleanTry
SqlDbType.VarChar, 50, _Role.Tables(“Role”).Rows(0).Item(“RoleName”))MyBase.AddParameter(“@RoleDescription”, _SqlDbType.Text, _
Role.Tables(“Role”).Rows(0).Item( _
“RoleDescription”).ToString.Length, _Role.Tables(“Role”).Rows(0).Item(“RoleDescription”))MyBase.AddParameter(“@Ranking”, _
SqlDbType.TinyInt, 1, _Role.Tables(“Role”).Rows(0).Item(“Ranking”))
‘Execute the stored procedureUpdateRole = ExecuteStoredProcedure()Catch ExceptionErr As Exception
Throw New System.Exception(ExceptionErr.Message, _ExceptionErr.InnerException)
End TryEnd Function
The next function that you add to your data access component is the UpdateUserfunction Again, onlythe SQL Server version is listed and the only differences between this version and the Oracle version arethe data types used in the Parameterscollection
You set the SQLproperty in the base class to the stored procedure being executed and call the
InitializeCommandmethod in the base class to initialize the Commandobject You then add the parameters to the Parameterscollection and pass the appropriate values using the data in the UserDataSet
Public Function UpdateUser(ByVal User As DataSet) As BooleanTry
SqlDbType.VarChar, 15, _User.Tables(“User”).Rows(0).Item(“LoginName”))MyBase.AddParameter(“@Password”, _
SqlDbType.VarChar, 30, _
Trang 18User.Tables(“User”).Rows(0).Item(“Password”))MyBase.AddParameter(“@FirstName”, _
SqlDbType.VarChar, 30, _User.Tables(“User”).Rows(0).Item(“FirstName”))MyBase.AddParameter(“@LastName”, _
SqlDbType.VarChar, 30, _User.Tables(“User”).Rows(0).Item(“LastName”))MyBase.AddParameter(“@Email”, _
SqlDbType.VarChar, 50, _User.Tables(“User”).Rows(0).Item(“Email”))MyBase.AddParameter(“@Phone”, _
SqlDbType.VarChar, 20, _User.Tables(“User”).Rows(0).Item(“Phone”))MyBase.AddParameter(“@Status”, _
SqlDbType.Bit, 1, _User.Tables(“User”).Rows(0).Item(“Status”))MyBase.AddParameter(“@GroupID”, _
SqlDbType.UniqueIdentifier, 16, _User.Tables(“User”).Rows(0).Item(“GroupID”))MyBase.AddParameter(“@RoleID”, _
SqlDbType.UniqueIdentifier, 16, _User.Tables(“User”).Rows(0).Item(“RoleID”))MyBase.AddParameter(“@ManagerID”, _
SqlDbType.UniqueIdentifier, 16, _User.Tables(“User”).Rows(0).Item(“ManagerID”))
After all the parameters are added to the Parameterscollection, you execute the stored procedure bycalling the ExecuteStoredProceduremethod in the base class You handle any errors that may occur
in the Catchblock
‘Execute the stored procedureUpdateUser = ExecuteStoredProcedure()Catch ExceptionErr As Exception
Throw New System.Exception(ExceptionErr.Message, _ExceptionErr.InnerException)
End TryEnd Function
The next step is to add the appropriate functions to the business logic component You add theUpdateRolefunction in the WBLRolesclass next The code for this function is not listed here but essentially mirrors the code that you added in the AddRolefunction in Chapter 11
You then add the UpdateUserfunction in the WBLUsersclass Because the password may or may not be updated, you cannot use the ValidateUserDatafunction to validate the data Instead, yourUpdateUserfunction contains the code to validate the data The only major difference in this functionfrom the other functions that you’ve added is the way you handle validating the password To that end,only the code for the password validation will be listed here
First, you need to determine whether a password exists in the DataSet This is done by converting thecolumn to a string using the ToStringmethod, trimming any blanks spaces using the Trimmethod,and finally checking the length using the Lengthfunction If the password is blank, you set it to aDBNullvalue using the DBNullfunction
Trang 19If the password is not blank, you validate the password using the IsValidPasswordfunction and thenhash the password using the HashPasswordfunction:
‘Validate the password
If User.Tables(“User”).Rows(0).Item( _
“Password”).ToString.Trim.Length = 0 Then
‘The old password is not being updated so set it to NullUser.Tables(“User”).Rows(0).Item(“Password”) = DBNull.ValueElse
‘A new password has been supplied
If Not IsValidPassword(User.Tables( _
“User”).Rows(0).Item(“Password”)) ThenThrow New System.Exception(strErrorMessage)Else
‘Hash the passwordUser.Tables(“User”).Rows(0).Item(“Password”) = _HashPassword(User.Tables(“User”).Rows(0).Item( _
“Password”))End If
End If
You add code to the ActionUpdateprocedure in the Admin form next You add the appropriate code toupdate a role under the Case “Roles”statement as follows First, this code initializes a new instance ofthe business logic component Then you get a new Role DataSetin the objDataSetobject and initial-ize a new DataRowobject
Case “Roles”
‘Initialize a new instance of the business logic componentUsing objRoles As New WroxBusinessLogic.WBLRoles( _strCompany, strApplication)
‘Get a new Role DataSetobjDataSet = objRoles.GetNewRoleDS()
‘Initialize a datarow object from the Role DataSetDim objDataRow As Data.DataRow = _
objDataSet.Tables(“Role”).NewRow
You then set the values in the DataRowobject using the input fields from the Role Details section of theRoles screen After the DataRowobject is populated with the appropriate data, you add the DataRowobject to the DataSet
The call to the UpdateRolemethod in the business logic component is encapsulated in an If Thenstatement to handle any errors that might be thrown
‘Set the values in the DataRowobjDataRow.Item(“RoleID”) = New Guid(txtRoleID.Text)objDataRow.Item(“RoleName”) = txtRoleName.TextobjDataRow.Item(“RoleDescription”) = _
txtRoleDescription.TextobjDataRow.Item(“Ranking”) = _CType(txtRanking.Text, Byte)
‘Add the DataRow to the DataSetobjDataSet.Tables(“Role”).Rows.Add(objDataRow)
‘Update the Role in the database
Trang 20If Not objRoles.UpdateRole(objDataSet) ThenThrow New Exception(“Update Role Failed”)End If
End Using
After the role is successfully updated, you clear the fields in the Role Details section of the Roles screen
by setting the Textproperty of the text boxes to an empty string Then you call the LoadRolesdure to update the list of roles to reflect the changes just made
proce-‘Clear the input fieldstxtRoleID.Text = String.EmptytxtRoleName.Text = String.EmptytxtRoleDescription.Text = String.EmptytxtRanking.Text = String.Empty
of the Users screen
Case “Users”
‘Initialize a new instance of the business logic componentUsing objUsers As New WroxBusinessLogic.WBLUsers( _strCompany, strApplication)
‘Get a new User DataSetobjDataSet = objUsers.GetNewUserDS()
‘Initialize a datarow object from the Role DataSetDim objDataRow As Data.DataRow = _
objDataSet.Tables(“User”).NewRow
‘Set the values in the DataRowobjDataRow.Item(“UserID”) = New Guid(txtUserID.Text)objDataRow.Item(“LoginName”) = txtLogin.Text
objDataRow.Item(“Password”) = txtPassword.TextobjDataRow.Item(“FirstName”) = txtFirstName.TextobjDataRow.Item(“LastName”) = txtLastName.TextobjDataRow.Item(“Email”) = txtEmail.TextobjDataRow.Item(“Phone”) = txtPhone.TextobjDataRow.Item(“Status”) = optStatusActive.CheckedobjDataRow.Item(“GroupID”) = _
cboUserGroup.SelectedItem.Item(“GroupID”)objDataRow.Item(“RoleID”) = _
cboUserRole.SelectedItem.Item(“RoleID”)
If cboUserManager.SelectedIndex <> -1 ThenobjDataRow.Item(“ManagerID”) = _cboUserManager.SelectedItem.item(“ManagerID”)End If
After all the values are set in the DataRowobject, you add the DataRowobject to the DataSet Then youcall the UpdateUsermethod in the business logic component and encapsulate that call in an If Thenstatement to handle any errors that might be thrown from that call
Trang 21If all was successful, you clear the Textproperty of the text boxes in the User Details section of the Usersscreen by setting them to an empty string
Next, you call the LoadManagersand LoadUsersprocedures to reload the list of managers in thecboUserManagercombo box and the list of users in the Users screen You then set the SelectedIndexproperty of the combo boxes to a value of -1, which causes no entries to be selected
‘Add the DataRow to the DataSetobjDataSet.Tables(“User”).Rows.Add(objDataRow)
‘Update the User in the database
If Not objUsers.UpdateUser(objDataSet) ThenThrow New Exception(“Update User Failed”)End If
End Using
‘Clear the input fieldstxtUserID.Text = String.EmptytxtLogin.Text = String.EmptytxtPassword.Text = String.EmptytxtFirstName.Text = String.EmptytxtLastName.Text = String.EmptytxtEmail.Text = String.EmptytxtPhone.Text = String.EmptyoptStatusActive.Checked = TruetxtUserUpdateDate.Text = String.Empty
‘Reload the Managers combo boxCall LoadManagers()
‘Reload the Users listCall LoadUsers()cboUserGroup.SelectedIndex = -1cboUserRole.SelectedIndex = -1cboUserManager.SelectedIndex = -1
This completes the code for the Admin form and you are now able to update roles and users as you sawwhen you tested your changes The only functionality that has not been implemented for roles and users
is delete functionality
Updating T imesheets
The way that a timesheet is displayed in the TimeSheet form and the way that it is stored in the databaseare totally different, as you saw when you built the usp_SelectTimeSheetstored procedure in the lastchapter When a user saves a timesheet, you update the hours for each project for each day of the week
in the TimeSheetItems table
This actually simplifies the update process, as you have the TimeSheetItemID and the hours to beupdated in the TimeSheet DataSet All you need to do is iterate through each row in the DataSetandperform a call to the update stored procedure for a timesheet to update the hours for each day and eachproject
Trang 22Remember that the TimeSheet DataSetcontains one project per row in the DataSetand a column foreach business day of the week for that project You will be calling the update stored procedure for eachday of the week in each row Therefore, you basically call the update stored procedure five times for eachrow of data in the DataSet You see how this is implemented in the SaveTimeSheetfunction in thedata access component in the next exercise.
In this Try It Out, you add to the TimeSheet form the functionality for a user to update and submit his orher timesheet, as well as the functionality for a manager to approve a timesheet
Try It Out Completing the TimeSheet Form
To complete this exercise:
1. Open your Time Tracker application in Visual Studio 2005 if it is not still open.
2. View the Server Explorer window and click the Auto Hide icon on the window to keep it visibleand then view the Stored Procedures node for your database
3. Create the usp_UpdateTimeSheetItemstored procedure first This stored procedure updates
a single timesheet item in a timesheet for a user Readers using SQL Server should right-click the Stored Procedures and choose Add New Stored Procedure from the context menu Readersusing Oracle should use their favorite Oracle tool such as iSQL *Plus to create the stored proce-dures Enter the code for the following stored procedure:
AS
BEGIN TRYUPDATE TimeSheetItemsSET Hours = @HoursWHERE TimeSheetItemID = @TimeSheetItemIDEND TRY
BEGIN CATCHBEGINRAISERROR(‘Update timesheet item failed.’,18,1)RETURN
ENDEND CATCH
Click the Save icon on the toolbar to create the stored procedure
Oracle
CREATE OR REPLACE PROCEDURE usp_UpdateTimeSheetItem(
inTimeSheetItemID CHAR,inHours NUMBER)
ASBEGIN
Trang 23UPDATE TimeSheetItemsSET Hours = inHoursWHERE TimeSheetItemID = inTimeSheetItemID;
EXCEPTIONWHEN OTHERS THENRAISE_APPLICATION_ERROR( -20999,’Update timesheet item failed.’);
RETURN;
END;
Click the Execute button to have the stored procedure created in your database
4. Create the usp_SubmitTimeSheetstored procedure next This stored procedure updates atimesheet, marking it as submitted and preventing the user from editing the contents SQLServer users should right-click the Stored Procedures node in the Server Explorer and chooseAdd New Stored Procedure and Oracle users should use their Oracle tool Enter the follow-ing code:
SQL Server
CREATE PROCEDURE usp_SubmitTimeSheet
(
@TimeSheetID UNIQUEIDENTIFIER)
AS
BEGIN TRY
UPDATE TimeSheetsSET Submitted = 1WHERE TimeSheetID = @TimeSheetIDEND TRY
BEGIN CATCH
BEGINRAISERROR(‘Submit timesheet failed.’,18,1)RETURN
ENDEND CATCH
Click the Save icon on the toolbar to have the stored procedure created in your database
Oracle
CREATE OR REPLACE PROCEDURE usp_SubmitTimeSheet
(
inTimeSheetID CHAR)
AS
BEGIN
UPDATE TimeSheetsSET Submitted = 1WHERE TimeSheetID = inTimeSheetID;
EXCEPTIONWHEN OTHERS THENRAISE_APPLICATION_ERROR( -20999,’Submit timesheet failed.’);
RETURN;
END;
Trang 24Click the Execute button to have the stored procedure created in your database
5. The final stored procedure to create is the usp_ApproveTimeSheetstored procedure Thisstored procedure updates the status of a timesheet, marking it as approved by a manager SQLServer users should right-click the Stored Procedures node in the Server Explorer and chooseAdd New Stored Procedure and Oracle users should use their Oracle tool Enter the followingcode:
AS
BEGIN TRYUPDATE TimeSheetsSET ApprovalDate = GETDATE(),ManagerID = @ManagerIDWHERE TimeSheetID = @TimeSheetIDEND TRY
BEGIN CATCH BEGINRAISERROR(‘Approve timesheet failed.’,18,1)RETURN
ENDEND CATCH
Click the Save icon on the toolbar to have the stored procedure created in your database
Oracle
CREATE OR REPLACE PROCEDURE usp_ApproveTimeSheet(
inTimeSheetID CHAR,inManagerID CHAR)
AS
BEGINUPDATE TimeSheetsSET ApprovalDate = SYSDATE,ManagerID = inManagerIDWHERE TimeSheetID = inTimeSheetID;
EXCEPTIONWHEN OTHERS THENRAISE_APPLICATION_ERROR( -20999,’Approve timesheet failed.’);
RETURN;
END;
Click the Execute button to have the stored procedure created in your database
6. View the code in the WDATimeSheetsclass in your data access component The first function toadd in this class is the SaveTimeSheetfunction Add the following code to this class:
Trang 25SqlDbType.TinyInt, 1, Nothing)
‘Process all rows in the tableFor intIndex As Integer = 0 To _TimeSheet.Tables(“TimeSheet”).Rows.Count - 2
‘Update Monday’s HoursMyBase.Command.Parameters.Item(“@TimeSheetItemID”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“MondayTimeSheetItemID”)MyBase.Command.Parameters.Item(“@Hours”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“MondayHours”)SaveTimeSheet = ExecuteStoredProcedure()
‘Update Tuesday’s HoursMyBase.Command.Parameters.Item(“@TimeSheetItemID”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“TuesdayTimeSheetItemID”)MyBase.Command.Parameters.Item(“@Hours”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“TuesdayHours”)SaveTimeSheet = ExecuteStoredProcedure()
‘Update Wednesday’s HoursMyBase.Command.Parameters.Item(“@TimeSheetItemID”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“WednesdayTimeSheetItemID”)MyBase.Command.Parameters.Item(“@Hours”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“WednesdayHours”)SaveTimeSheet = ExecuteStoredProcedure()
‘Update Thursday’s HoursMyBase.Command.Parameters.Item(“@TimeSheetItemID”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“ThursdayTimeSheetItemID”)MyBase.Command.Parameters.Item(“@Hours”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“ThursdayHours”)SaveTimeSheet = ExecuteStoredProcedure()
‘Update Friday’s HoursMyBase.Command.Parameters.Item(“@TimeSheetItemID”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“FridayTimeSheetItemID”)MyBase.Command.Parameters.Item(“@Hours”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“FridayHours”)
Trang 26SaveTimeSheet = ExecuteStoredProcedure()Next
Catch ExceptionErr As ExceptionThrow New System.Exception(ExceptionErr.Message, _ExceptionErr.InnerException)
End TryEnd Function
OracleClient.OracleType.Number, 3, Nothing)
‘Process all rows in the tableFor intIndex As Integer = 0 To _TimeSheet.Tables(“TimeSheet”).Rows.Count - 2
‘Update Monday’s HoursMyBase.Command.Parameters.Item(“inTimeSheetItemID”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“MondayTimeSheetItemID”).ToStringMyBase.Command.Parameters.Item(“inHours”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“MondayHours”)SaveTimeSheet = ExecuteStoredProcedure()
‘Update Tuesday’s HoursMyBase.Command.Parameters.Item(“inTimeSheetItemID”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“TuesdayTimeSheetItemID”).ToStringMyBase.Command.Parameters.Item(“inHours”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“TuesdayHours”)SaveTimeSheet = ExecuteStoredProcedure()
‘Update Wednesday’s HoursMyBase.Command.Parameters.Item(“inTimeSheetItemID”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“WednesdayTimeSheetItemID”).ToStringMyBase.Command.Parameters.Item(“inHours”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“WednesdayHours”)SaveTimeSheet = ExecuteStoredProcedure()
‘Update Thursday’s HoursMyBase.Command.Parameters.Item(“inTimeSheetItemID”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“ThursdayTimeSheetItemID”).ToStringMyBase.Command.Parameters.Item(“inHours”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“ThursdayHours”)
Trang 27SaveTimeSheet = ExecuteStoredProcedure()
‘Update Friday’s HoursMyBase.Command.Parameters.Item(“inTimeSheetItemID”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“FridayTimeSheetItemID”).ToStringMyBase.Command.Parameters.Item(“inHours”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“FridayHours”)SaveTimeSheet = ExecuteStoredProcedure()Next
Catch ExceptionErr As ExceptionThrow New System.Exception(ExceptionErr.Message, _ExceptionErr.InnerException)
End TryEnd Function
7. Add the SubmitTimeSheetfunction in the same class next Add the following code:
Throw New System.Exception(ExceptionErr.Message, _ExceptionErr.InnerException)
End TryEnd Function
Throw New System.Exception(ExceptionErr.Message, _ExceptionErr.InnerException)
End TryEnd Function
Trang 288. The final function to add in the WDATimeSheetsclass is the ApproveTimeSheetfunction Addthe following code to this class:
SQL Server
Public Function ApproveTimeSheet(ByVal TimeSheetID As Guid, _ByVal ManagerID As Guid) As Boolean
TryMyBase.SQL = “usp_ApproveTimeSheet”
‘Initialize the Command objectMyBase.InitializeCommand()
‘Add the Parameters to the Parameters collectionMyBase.AddParameter(“@TimeSheetID”, _
SqlDbType.UniqueIdentifier, 16, TimeSheetID)MyBase.AddParameter(“@ManagerID”, _
SqlDbType.UniqueIdentifier, 16, ManagerID)
‘Execute the stored procedureApproveTimeSheet = ExecuteStoredProcedure()Catch ExceptionErr As Exception
Throw New System.Exception(ExceptionErr.Message, _ExceptionErr.InnerException)
End TryEnd Function
Oracle
Public Function ApproveTimeSheet(ByVal TimeSheetID As Guid, _ByVal ManagerID As Guid) As Boolean
TryMyBase.SQL = “usp_ApproveTimeSheet”
‘Initialize the Command objectMyBase.InitializeCommand()
‘Add the Parameters to the Parameters collectionMyBase.AddParameter(“inTimeSheetID”, _
OracleClient.OracleType.Char, 36, TimeSheetID.ToString)MyBase.AddParameter(“inManagerID”, _
OracleClient.OracleType.Char, 36, ManagerID.ToString)
‘Execute the stored procedureApproveTimeSheet = ExecuteStoredProcedure()Catch ExceptionErr As Exception
Throw New System.Exception(ExceptionErr.Message, _ExceptionErr.InnerException)
End TryEnd Function
9. Now it’s time to move to the WBLTimeSheetsclass in the business logic component to add theappropriate functions there The first function to add is the SaveTimeSheetfunction Add thefollowing code to this class:
Public Function SaveTimeSheet(ByVal TimeSheet As DataSet) As BooleanTry
‘Call the data component to save the timesheetReturn objWDATimeSheets.SaveTimeSheet(TimeSheet)Catch ExceptionErr As Exception
Throw New System.Exception(ExceptionErr.Message, _ExceptionErr.InnerException)
End TryEnd Function
Trang 2910. The SubmitTimeSheetfunction is next, so add the following code to the WBLTimeSheetsclass:Public Function SubmitTimeSheet(ByVal TimeSheetID As Guid) As Boolean
Try
‘Call the data component to submit the timesheetReturn objWDATimeSheets.SubmitTimeSheet(TimeSheetID)Catch ExceptionErr As Exception
Throw New System.Exception(ExceptionErr.Message, _ExceptionErr.InnerException)
End TryEnd Function
11. The ApproveTimeSheetfunction is the final function to be added to the business logic nent Add the following code:
compo-Public Function ApproveTimeSheet(ByVal TimeSheetID As Guid, _ByVal ManagerID As Guid) As Boolean
Try
‘Call the data component to approve the timesheetReturn objWDATimeSheets.ApproveTimeSheet(TimeSheetID, ManagerID)Catch ExceptionErr As Exception
Throw New System.Exception(ExceptionErr.Message, _ExceptionErr.InnerException)
End TryEnd Function
12. Now it’s time to add some code to the TimeSheet form, so view the code in the Code Editor.When users are finished editing a timesheet, they click the Save button to save the changes.Click the Class Name combo box and select btnSave, and in the Method Name combo box,select the Clickevent Add the following code to the btnSave_Clickprocedure:
Private Sub btnSave_Click(ByVal sender As Object, _ByVal e As System.EventArgs) Handles btnSave.Click
‘Initialize a new instance of the business logic componentUsing objTimeSheets As New WroxBusinessLogic.WBLTimeSheets( _strCompany, strApplication)
Try
‘Save the timesheet changes
If Not objTimeSheets.SaveTimeSheet(objTimeSheetDS) ThenThrow New Exception(“Save TimeSheet Failed”)End If
‘Display a statusbar messageToolStripStatus.Text = “Timesheet saved”
Catch ExceptionErr As ExceptionMessageBox.Show(ExceptionErr.Message, strAppTitle)End Try
End UsingEnd Sub
13. When users complete their timesheet for the week, they will submit their timesheet for approval.Click the Class Name combo box and select btnSubmit, and in the Method Name combo boxselect the Clickevent Add the following code to the btnSubmit_Clickprocedure:
Trang 30Private Sub btnSubmit_Click(ByVal sender As Object, _ByVal e As System.EventArgs) Handles btnSubmit.Click
‘Initialize a new instance of the business logic componentUsing objTimeSheets As New WroxBusinessLogic.WBLTimeSheets( _strCompany, strApplication)
Try
‘Submit the timesheet
If Not objTimeSheets.SubmitTimeSheet( _New Guid(objTimeSheetDS.Tables(“TimeSheet”).Rows(0).Item( _
“TimeSheetID”).ToString)) ThenThrow New Exception(“Submit TimeSheet Failed”)End If
‘Reload the timesheet so it becomes read-onlyCall LoadTimeSheet(cboWeekEnding)
‘Display a statusbar messageToolStripStatus.Text = “Timesheet submitted”
Catch ExceptionErr As ExceptionMessageBox.Show(ExceptionErr.Message, strAppTitle)End Try
End UsingEnd Sub
14. When managers approve a timesheet for a user, they click the Approve button You need to add some code to the Clickevent for that button Click the Class Name combo box and selectbtnApprove, and in the Method Name combo box select the Clickevent Add the followingcode to the btnApprove_Clickprocedure:
Private Sub btnApprove_Click(ByVal sender As Object, _ByVal e As System.EventArgs) Handles btnApprove.Click
‘Initialize a new instance of the business logic componentUsing objTimeSheets As New WroxBusinessLogic.WBLTimeSheets( _strCompany, strApplication)
Try
‘Submit the timesheet
If Not objTimeSheets.ApproveTimeSheet( _New Guid(objTimeSheetDS.Tables(“TimeSheet”).Rows(0).Item( _
“TimeSheetID”).ToString), New Guid(strManagerID)) ThenThrow New Exception(“Approve TimeSheet Failed”)End If
‘Display a statusbar messageToolStripStatus.Text = “Timesheet approved”
Catch ExceptionErr As ExceptionMessageBox.Show(ExceptionErr.Message, strAppTitle)End Try
End UsingEnd Sub
That’s all the code that’s needed to complete the functionality in your TimeSheet form To test yourchanges, start your project and log in as a user When the TimeSheet form is displayed, complete thetimesheet and then click the Save button Your timesheet will be saved and you’ll see a message in thestatus bar indicating that the timesheet was saved, as shown in Figure 13-3 You can continue to makechanges to the timesheet and save it again if you want
Trang 31Figure 13-3
Now test the functionality of the Submit button Click the Submit button and you see a message in thestatus bar indicating that the timesheet was submitted, as shown in Figure 13-4 You’ll also notice thatthe icon next to the Submit button has been changed to a locked status and the timesheet is read-onlyand will not allow any changes
Figure 13-4
You have exercised all of the functionality from a user’s standpoint so close the TimeSheet form Startyour project again and this time log in as a manager When the TimeSheet form is displayed, select theuser in the Employee combo box who you submitted the timesheet for and select the appropriate week
Trang 32ending date in the Week Ending combo box When the timesheet appears, click the Approve button and you’ll notice a message in the status bar indicating that the timesheet was approved, as shown inFigure 13-5.
Figure 13-5
How It WorksThe first stored procedure that you create in this exercise is the usp_UpdateTimeSheetItemstored procedure This is a simple UPDATEstored procedure that will update a single row in the TimeSheetItemstable
In the SQL Server version that follows, you can see that there are only two input parameters to thisstored procedure: the TimeSheetItemIDof the timesheet item to be updated, and the hours that should
be updated in the Hours column
The UPDATEstatement is also simple and updates the Hours column where the TimeSheetItemIDin theTimeSheetItems table matches the @TimeSheetItemIDinput parameter The appropriate error-handlingcode has been added to handle any errors that may occur
AS
BEGIN TRYUPDATE TimeSheetItemsSET Hours = @HoursWHERE TimeSheetItemID = @TimeSheetItemIDEND TRY
Trang 33BEGIN CATCH
BEGINRAISERROR(‘Update timesheet item failed.’,18,1)RETURN
ENDEND CATCH
In the Oracle version, the same two input parameters have been supplied with data types appropriatefor Oracle The UPDATEstatement in this stored procedure is the same as the SQL Server version andupdates a single row of data in the TimeSheetItems table
Error handling is included to catch any exceptions that may be thrown and will return an appropriateerror message to the caller if an error is thrown
Oracle
CREATE OR REPLACE PROCEDURE usp_UpdateTimeSheetItem
(
inTimeSheetItemID CHAR,inHours NUMBER)
AS
BEGIN
UPDATE TimeSheetItemsSET Hours = inHoursWHERE TimeSheetItemID = inTimeSheetItemID;
EXCEPTIONWHEN OTHERS THENRAISE_APPLICATION_ERROR( -20999,’Update timesheet item failed.’);
RETURN;
END;
Next, you create the usp_SubmitTimeSheetstored procedure The TimeSheets table contains theSubmitted column, which stores a BITvalue in SQL Server and a NUMBERvalue in Oracle When atimesheet is created, this column contains a value of 0, indicating that the timesheet has not been sub-mitted When users submit their timesheets, this column is updated to contain a value of 1, indicatingthat their timesheets have been submitted
The TimeSheet form contains the necessary logic to make the timesheet read-only when the submittedcolumn contains a value of 1
The SQL Server version of this stored procedure accepts only one parameter, the TimeSheetIDof thetimesheet to be updated The UPDATEstatement sets the value in the Submitted column to a value of 1,indicating that the timesheet has been submitted
The appropriate error handling is included in this stored procedure to handle any errors that may occurand will return the appropriate error message to the caller of this stored procedure
SQL Server
CREATE PROCEDURE usp_SubmitTimeSheet
(
@TimeSheetID UNIQUEIDENTIFIER)
Trang 34BEGIN TRYUPDATE TimeSheetsSET Submitted = 1WHERE TimeSheetID = @TimeSheetIDEND TRY
BEGIN CATCH BEGINRAISERROR(‘Submit timesheet failed.’,18,1)RETURN
ENDEND CATCH
The Oracle version of this stored procedure is similar to the SQL Server version and accepts only theTimeSheetIDof the timesheet being updated as its one and only input parameter The UPDATEstate-ment also mirrors its SQL Server counterpart, setting the value in the Submitted column to a value of 1.Error-handling code is also included to handle any exceptions thrown and to return the appropriateerror message back to the caller
Oracle
CREATE OR REPLACE PROCEDURE usp_SubmitTimeSheet(
inTimeSheetID CHAR)
AS
BEGINUPDATE TimeSheetsSET Submitted = 1WHERE TimeSheetID = inTimeSheetID;
EXCEPTIONWHEN OTHERS THENRAISE_APPLICATION_ERROR( -20999,’Submit timesheet failed.’);
RETURN;
END;
The final stored procedure you create in this exercise is usp_ApproveTimeSheet Managers using theTimeSheet form execute this stored procedure when they click the Approve button on the TimeSheet form.The SQL Server implementation of this stored procedure accepts two input parameters: the TimeSheetID
of the timesheet to be approved and the ManagerID of the manager approving the timesheet
The UPDATEstatement sets the ApprovalDate to the current date and time and updates the ManagerIDcolumn with the ManagerID passed in the @ManagerIDinput parameter The appropriate error handling
is included to handle any errors that may occur and to pass the appropriate error message to the caller ofthis stored procedure
SQL Server
CREATE PROCEDURE usp_ApproveTimeSheet(
@TimeSheetID UNIQUEIDENTIFIER,
Trang 35@ManagerID UNIQUEIDENTIFIER)
AS
BEGIN TRY
UPDATE TimeSheetsSET ApprovalDate = GETDATE(),ManagerID = @ManagerIDWHERE TimeSheetID = @TimeSheetIDEND TRY
BEGIN CATCH
BEGINRAISERROR(‘Approve timesheet failed.’,18,1)RETURN
ENDEND CATCH
The Oracle version of this stored procedure also accepts the TimeSheetIDand ManagerID as inputparameters using the data types that are appropriate for the Oracle schema The UPDATEstatement mirrors the functionality of its SQL Server counterpart, updating the ApprovalDate and ManagerIDcolumns
The appropriate error handling is included and raises an application error if the UPDATEstatement fails
It then returns the appropriate error message to the caller
Oracle
CREATE OR REPLACE PROCEDURE usp_ApproveTimeSheet
(
inTimeSheetID CHAR,inManagerID CHAR)
AS
BEGIN
UPDATE TimeSheetsSET ApprovalDate = SYSDATE,ManagerID = inManagerIDWHERE TimeSheetID = inTimeSheetID;
EXCEPTIONWHEN OTHERS THENRAISE_APPLICATION_ERROR( -20999,’Approve timesheet failed.’);
RETURN;
END;
The SaveTimeSheetfunction is created next in the data access component Only the SQL Server version
is shown here The only differences between the SQL Server and Oracle versions are the data types used
in the Parameterscollection
The first thing to do in this function is to set the SQLproperty in the base class to the stored procedure to
be executed Then you initialize the Commandobject by calling the InitializeCommandmethod in thebase class
Trang 36Because you will be making multiple calls to this stored procedure, you want to add the parameters tothe Parameterscollection, passing a value of Nothingto the AddParametermethod The actual valuesfor these parameters are set in the Forloop that follows:
Public Function SaveTimeSheet(ByVal TimeSheet As DataSet) As BooleanTry
SqlDbType.TinyInt, 1, Nothing)
Now you want to process each business day of the week for each project This is done in a Forloop thatprocesses each row in the TimeSheet DataSet Remember that each row in the TimeSheet DataSetcontains the hours for each business day of the week for a single project You use the Countproperty ofthe Rowsproperty in the DataSetto determine the number of rows to process and subtract 2 from that.Normally you subtract 1 from the Countproperty because the index of the Rowsproperty is a zero-based index However, here you must subtract 2 to account for the last row in the DataSet, which you
do not want to process Remember that the last row in the DataSetcontains the total row you added,which contains the total for each day of the week This is merely done for the display of the timesheet,
so users know how many hours they entered for each day
‘Process all rows in the tableFor intIndex As Integer = 0 To _TimeSheet.Tables(“TimeSheet”).Rows.Count – 2
To update Monday’s hours, you get the TimeSheetItemID for Monday from the DataSet, which is tained in the MondayTimeSheetItemIDcolumn, and set the value in the @TimeSheetItemID Parameter
con-in the Parameterscollection Then you get the hours entered for Monday from the MondayHourscolumn
in the DataSetand set the value for the @Hours Parameterin the Parameterscollection Finally, youcall the ExecuteStoredProceduremethod in the base class to update the hours for Monday for thisgiven project
You repeat this process for Tuesday, Wednesday, Thursday, and Friday This causes the hours for eachday of the week to be updated for a single project Then you start the loop over and update the hours foreach day of the week for the next project:
‘Update Monday’s HoursMyBase.Command.Parameters.Item(“@TimeSheetItemID”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“MondayTimeSheetItemID”)MyBase.Command.Parameters.Item(“@Hours”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“MondayHours”)SaveTimeSheet = ExecuteStoredProcedure()
‘Update Tuesday’s HoursMyBase.Command.Parameters.Item(“@TimeSheetItemID”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“TuesdayTimeSheetItemID”)
Trang 37MyBase.Command.Parameters.Item(“@Hours”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“TuesdayHours”)SaveTimeSheet = ExecuteStoredProcedure()
‘Update Wednesday’s HoursMyBase.Command.Parameters.Item(“@TimeSheetItemID”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“WednesdayTimeSheetItemID”)MyBase.Command.Parameters.Item(“@Hours”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“WednesdayHours”)SaveTimeSheet = ExecuteStoredProcedure()
‘Update Thursday’s HoursMyBase.Command.Parameters.Item(“@TimeSheetItemID”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“ThursdayTimeSheetItemID”)MyBase.Command.Parameters.Item(“@Hours”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“ThursdayHours”)SaveTimeSheet = ExecuteStoredProcedure()
‘Update Friday’s HoursMyBase.Command.Parameters.Item(“@TimeSheetItemID”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“FridayTimeSheetItemID”)MyBase.Command.Parameters.Item(“@Hours”).Value = _TimeSheet.Tables(“TimeSheet”).Rows(intIndex).Item( _
“FridayHours”)SaveTimeSheet = ExecuteStoredProcedure()Next
The Catchblock contains the code to handle any errors that may be thrown from the execution of thisstored procedure and will throw a new exception, passing the error received to the caller of this function:
Catch ExceptionErr As ExceptionThrow New System.Exception(ExceptionErr.Message, _ExceptionErr.InnerException)
End TryEnd Function
The next function you add to your data access component is the SubmitTimeSheetfunction This tion executes the usp_SubmitTimeSheetstored procedure, which marks the timesheet as submitted.The only differences between the SQL Server and Oracle versions are the data types used in the
func-Parameterscollection, so only the SQL Server version is listed here
This function accepts the TimeSheetIDparameter as its one and only input parameter, as does theusp_SubmitTimeSheetstored procedure The Submitted column in the TimeSheets table is set to avalue of 1in the stored procedure, which marks the timesheet as submitted
Public Function SubmitTimeSheet(ByVal TimeSheetID As Guid) As BooleanTry
MyBase.SQL = “usp_SubmitTimeSheet”
‘Initialize the Command objectMyBase.InitializeCommand()