Programming Visual Basic 2008 phần 5 docx

79 272 0
Programming Visual Basic 2008 phần 5 docx

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

Thông tin tài liệu

Project | 295 PROJECT ACCESS Load the Chapter 10 (Before) Code project, either through the New Project tem- plates or by accessing the project directly from the installation directory. To see the code in its final form, load Chapter 10 (After) Code instead. Reference the Data Namespaces The Library Project code has references to several of the important .NET namespaces, such as System, System.Windows.Forms, and Microsoft.VisualBasic. However, it doesn’t yet reference any of the ADO.NET namespaces. (Recall that “referencing” means accessing a .NET DLL in a project and using its types in your code.) Before using them in code, we need to create references to them. This is done through the project properties window, on the References tab. You’ll see a list of those assemblies already referenced by the application (see Figure 10-9). To add new references, click the Add button just below the list, and select Reference if prompted for the type of reference to add. On the Add Reference form, the .NET tab should already be active. It’s pretty amazing to see just how many .NET assem- blies are installed on your system already. But don’t just sit there gawking: select both System.Data and System.Xml from the component list, and then click the OK button. The list of references in the project properties should now include both of the selected namespace libraries. We can now refer to classes in the System.Data namespace directly. But typing “System. Data” before each use of a data-related class will get tedious. We could sprinkle “Imports System.Data” statements throughout the files in the project, but Visual Studio provides a more centralized solution. Since you still have the References tab open, look down to the “Imported namespaces” section. The large checklist indicates which namespaces should be automatically imported throughout your application. These namespaces don’t require separate Imports statements in your code, but your source code acts as though you had added them anyway. Go ahead and select the checkbox next to the System.Data entry in this list. Then close the project properties window. Figure 10-9. References included in the Library Project 296 | Chapter 10: ADO.NET Most of the new code for this chapter appears in the General.vb file, so open it now. We will use two project-level (global) variables to manage the primary database con- nection to the Library database. The first variable, LibraryDB,isaSqlConnection object that uses our connection string for the Library database. A related object, HoldTransaction, will hold a SqlTransaction object when a transaction is in effect. Add these two lines to the General module. I put them just before the existing CenterText method. INSERT SNIPPET Insert Chapter 10, Snippet Item 1. Public LibraryDB As System.Data.SqlClient.SqlConnection Public HoldTransaction As System.Data.SqlClient.SqlTransaction Connecting to the Database Since the Library Project will depend so much on the database, we will build the SqlConnection object when first starting up the application. Maintaining the connection throughout the application goes against the advice I provided earlier that database connections should be short-lived. However, to keep the code as simple as possible for pur- poses of tutorial demonstration, I have chosen this approach. Also, because the Library Project is designed for a small installation base, it does not have the requirement of being highly scalable. The ConnectDatabase procedure contains all the code needed to create this object. For now, I’ve just hardcoded the connection string into the routine. In a later chap- ter, we’ll include that connection information as part of a configuration system. Add the following routine to your General module. Make sure you change the reference to “MYSYSTEM” to whatever is needed on your own system. INSERT SNIPPET Insert Chapter 10, Snippet Item 2. Public Function ConnectDatabase( ) As Boolean ' Connect to the database. Return True on success. Dim connectionString As String ' Initialize. HoldTransaction = Nothing Project | 297 ' Build the connection string. ' !!! WARNING: Hardcoded for now. connectionString = "Data Source=MYSYSTEM\SQLEXPRESS;" & _ "Initial Catalog=Library;Integrated Security=true" ' Attempt to open the database. Try LibraryDB = New SqlClient.SqlConnection(connectionString) LibraryDB.Open( ) Catch ex As Exception GeneralError("ConnectDatabase", ex) Return False End Try ' Success. Return True End Function This project’s “main” routine is actually the MyApplication_Startup application event, from the ApplicationEvents.vb source code file. (That’s one that you will have to use the Show All Files button to see.) To build the connection object at startup, add the following code to the end of that event handler. INSERT SNIPPET Insert Chapter 10, Snippet Item 3. ' Connect to the database. If (ConnectDatabase( ) = False) Then Me.HideSplashScreen( ) e.Cancel = True Return End If When the user exits the Library application, the code will call the CleanUpProgram method to properly dispose of the connection object. Return to the General.vb mod- ule, and add that method. INSERT SNIPPET Insert Chapter 10, Snippet Item 4. Public Sub CleanUpProgram( ) ' Prepare to exit the program. On Error Resume Next LibraryDB.Close( ) End Sub 298 | Chapter 10: ADO.NET To simplify things, we’ll call this routine from the application’s MyApplication_ Shutdown event handler, back in the ApplicationEvents.vb file. INSERT SNIPPET Insert Chapter 10, Snippet Item 5. CleanUpProgram( ) Interacting with the Database Now that the database connection is established, it’s time to do something with it. The first four centralized routines implement much of the code we discussed earlier: the creation of data readers and tables, and the processing of general SQL code. Add them to the General module. INSERT SNIPPET Insert Chapter 10, Snippet Item 6. This snippet adds the following seven routines: Function CreateDataTable Given a SQL statement, retrieve its results from the database, and put it all in a DataTable object. A SqlDataAdapter connects the SqlDataReader with the DataTable. Function CreateReader Given a SQL statement, retrieve its results from the database, returning the asso- ciated SqlDataReader object. Sub ExecuteSQL Send a SQL statement to the database for processing. Function ExecuteSQLReturn Send a SQL statement to the database for processing, returning a single result value. Sub TransactionBegin Begin a new transaction. Sub TransactionCommit Commit the transaction, making all changes permanent. Sub TransactionRollback Roll back the transaction, undoing any changes that were part of the transaction. None of these routines include their own error-processing code; they either suppress errors with an “On Error Resume Next” statement, or rely on the calling routine to Project | 299 trap errors. This lets the calling routine take specific action based on the type of error generated. All of these routines are pretty similar to one another. Here is the code for CreateReader; one interesting part is the use of the HoldTransaction object when a transaction is in effect. Public Function CreateReader(ByVal sqlText As String) _ As SqlClient.SqlDataReader ' Given a SQL statement, return a data reader. Dim dbCommand As SqlClient.SqlCommand Dim dbScan As SqlClient.SqlDataReader ' Try to run the statement. Note that no error ' trapping is done here. It is up to the calling ' routine to set up error checking. dbCommand = New SqlClient.SqlCommand(sqlText, LibraryDB) If Not (HoldTransaction Is Nothing) Then _ dbCommand.Transaction = HoldTransaction dbScan = dbCommand.ExecuteReader( ) dbCommand = Nothing Return dbScan End Function Processing Data Values Building SQL statements by hand involves a lot of string manipulation, plus condi- tional processing for those times when data may be missing. For instance, if you want to store a text value in the database, you have to prepare it for use by a SQL statement (special processing for single quote marks), but if the text value is zero- length, you pass the word NULL in the statement instead. All of this data prepara- tion can clog up your code, so why not centralize it? The eight routines in this sec- tion either prepare data for use in SQL statements, or adjust retrieved data for use in the application. INSERT SNIPPET Insert Chapter 10, Snippet Item 7. DBCombo Takes the numeric code associated with a selected item in a ComboBox control and returns it as a string. If no item is selected or the value is –1, the routine returns NULL. DBDate(String) Given a string containing a formatted date, returns a date ready for use in a SQL statement. DBDate(Date) Given a true date value, returns a string date ready for use in a SQL statement. 300 | Chapter 10: ADO.NET DBGetDecimal Returns a decimal number from a result set, even if the field contains a NULL value. DBGetInteger Returns an integer number from a result set, even if the field contains a NULL value. DBGetText Returns a string from a result set, even if the field contains a NULL value. DBNum Prepares a number for use in a SQL statement. DBText Prepares a string for use in a SQL statement. Here is the code for the DBText routine. Strings in SQL statements must be sur- rounded by single quotes, and any embedded single quotes must be doubled. Public Function DBText(ByVal origText As String) As String ' Prepare a string for insertion in a SQL statement. If (Trim(origText) = "") Then Return "NULL" Else Return "'" & Replace(origText, "'", "''") & "'" End If End Function System-Level Configuration The last blocks of code support the quick update and retrieval of system-wide config- uration values stored in the SystemValue table of the Library database. The GetSystemValue routine returns the current setting of a configuration value when sup- plied with the value name. SetSystemValue updates (or adds, if needed) a named con- figuration value. Both of these routines appear in the General module. INSERT SNIPPET Insert Chapter 10, Snippet Item 8. Public Function GetSystemValue( _ ByVal valueName As String) As String ' Return the data portion of a system value ' name-data pair. Dim sqlText As String Dim returnValue As String ' Retrieve the value. returnValue = "" Project | 301 sqlText = "SELECT ValueData FROM SystemValue WHERE " & _ "UPPER(ValueName) = " & DBText(UCase(valueName)) Try returnValue = DBGetText(ExecuteSQLReturn(sqlText)) Catch ex As Exception GeneralError("GetSystemValue", ex) End Try Return returnValue End Function Public Sub SetSystemValue(ByVal valueName As String, _ ByVal valueData As String) ' Update a record in the SystemValue table. Dim sqlText As String Try ' See if the entry already exists. sqlText = "SELECT COUNT(*) FROM SystemValue WHERE " & _ "UPPER(ValueName) = " & DBText(UCase(valueName)) If (CInt(ExecuteSQLReturn(sqlText)) > 0) Then ' Value already exists. sqlText = "UPDATE SystemValue " & _ "SET ValueData = " & DBText(valueData) & _ " WHERE UPPER(ValueName) = " & _ DBText(UCase(valueName)) Else ' Need to create value. sqlText = "INSERT INTO SystemValue " & _ (ValueName, ValueData) VALUES (" & _ DBText(valueName) & ", " & _ DBText(valueData) & ")" End If ' Update the value. ExecuteSQL(sqlText) Catch ex As System.Exception GeneralError("SetSystemValue", ex) End Try End Sub The GetSystemValue routine is clear. It simply retrieves a single value from the data- base. SetSystemValue has to first check whether the configuration value to update already exists in the database. If it does, it modifies the records. Otherwise, it adds a full new record. To determine whether the record exists, it requests a count of records matching the system value name. It queries the database through our new ExecuteSqlReturn method, which returns a single value from a query. In this case, the value is the count of the matching records. sqlText = "SELECT COUNT(*) FROM SystemValue WHERE " & _ "UPPER(ValueName) = " & DBText(UCase(valueName)) If (CInt(ExecuteSQLReturn(sqlText)) > 0) Then 302 | Chapter 10: ADO.NET Using the GetSystemValue routine is easy, so let’s use it right now. Go back to the MyApplication_Startup event handler in ApplicationEvents.vb, and add the following code to the end of the routine. INSERT SNIPPET Insert Chapter 10, Snippet Item 9. ' Check the database version. Dim productionDBVersion As String productionDBVersion = Trim(GetSystemValue("DatabaseVersion")) If (CInt(Val(productionDBVersion)) <> UseDBVersion) Then MsgBox("The program cannot continue due to an " & _ "incompatible database. The current database " & _ "version is '" & productionDBVersion & _ "'. The application version is '" & _ UseDBVersion & "'.", _ MsgBoxStyle.OkOnly Or MsgBoxStyle.Critical, ProgramTitle) CleanUpProgram( ) Me.HideSplashScreen( ) e.Cancel = True Return End If Once in a while, I found it necessary to modify the structure of a database to such an extent that older versions of an application either crashed, or would cause major data headaches. To prevent this, I added a database version setting, DatabaseVersion, and use this code block to test against it. If the program doesn’t match the expected data- base version, it will refuse to run. Now that we have some basic database access tools, we’re ready to start adding some real data interaction code to the Library application. 303 Chapter 11 CHAPTER 11 Security11 Secrets are funny things. With billions of people on the planet, there is no shortage of really interesting events and stories, but none of them will hold our interest if there is a secret to be discovered somewhere else. For instance, former associate director of the FBI, W. Mark Felt, revealed himself to be the famous “Deep Throat” of Watergate fame, but not before 30 years of speculation and whispering about this secret identity had passed by. Other secrets are just as intriguing, even if we are in on the secret. Superman is fascinating in part due to his secret alter ego, Clark Kent. Many books include the word Secret in their titles to make them and their topics more interesting, titles such as Japanese Cooking Secrets. In this era of information overload and increasingly permissive moral standards on television, secrets seem to be scarce. But everyone has important information that he needs to keep protected from others, and that includes the users of your programs. Fortunately, .NET programs and related data can be as secure as you need, if you use the security features available to you in the .NET Framework. Here’s a secret that I’ll tell right now: I really don’t know that much about computer security issues. Back in the early 1980s, I worked for a computer vendor that was com- ing out with its own Unix System V implementation. The company needed to confirm that its product would be sufficiently secure for governmental sales, and I was tasked with building a bibliography of computer security resources, including the famous “Orange Book,” a government security standards document whose title has no rhyme. Although I don’t recall many of the security details, I do remember that it would take several city garbage trucks to haul away all the available materials on computer secu- rity. The bibliography I developed was more than 40 pages long! And that was just the table of contents. One article that I do recall was quite interesting. It discussed how passwords are generated in Unix systems, at least back when AT&T was in charge. The interesting part was that the entire algorithm was printed in a publicly available book. Anyone could examine the book and see how the passwords were generated. And if you were familiar with Unix, you knew that each user’s encrypted password was stored in plain text in the file /etc/passwd. But it wasn’t a big deal. 304 | Chapter 11: Security Although the method for deriving the password was public knowledge, and although you could see everyone’s encrypted password, Unix was still considered secure enough for use even in the military. Security Features in .NET Security in .NET involves many features, but they fall generally into three major areas: Internal security Classes and class members in .NET can be protected via user-based or role- based security. This Code Access Security (CAS) exists to keep unauthorized users from accessing powerful libraries of .NET features. Only those users meet- ing a minimum or specific set of rights can use those protected features. External security Since anyone can develop and distribute a .NET application, it’s important to protect system resources from malicious code. This is a big issue, especially with the ongoing reports of hackers taking advantage of “buffer overrun” problems in released software from Microsoft and other vendors. Just as CAS keeps code from accessing certain features of a class, it interacts with the operating system to keep rogue code from accessing some or all files and directories, registry entries, network resources, hardware peripherals, or other .NET assemblies based on in-effect security policies. Data security Programs and computer resources aren’t the only things that need to be pro- tected. Some highfalutin users think their precious data is so important that it deserves to be protected through “special” software means. Encryption, digital signatures, and other cryptographic features provide the “special” support needed for such data. Because the Library Project interacts with a major external resource—a SQL Server database—it does deal with external security issues, although indirectly through ADO.NET and system security policies. Still, because of this book’s focus on typical business application development, this chapter will not discuss either internal secu- rity or external security issues. Instead, it will focus on data security topics, espe- cially the encryption of data. Cryptography and Encryption Knowing a secret is one thing. Keeping it safe and protected from others is another. Making sure an enemy doesn’t alter it while we’re blabbing—I mean, confiding—it to someone else is still another issue. Confirming that a secret coming from someone else is reliable is yet another issue. Making sure that I get the best deal on car insur- ance is again another issue entirely. [...]... probably didn’t even know that the humble Visual Basic addition operator (+) had dreams of flying, or of speaking Hungarian, or of bending steel Well, operators are people, too And now their dreams can be fulfilled because Visual Basic supports operator overloading This chapter will show how you can direct the body-building enhancement process for the various Visual Basic operators I’ll also introduce extension... NET are simply wrappers around the older Cryptography API (CAPI), a pre-.NET DLL SHA1Managed uses a 160-bit hash code • Three other classes—SHA 256 Managed, SHA384Managed, and SHA512Managed—are similar to the SHA1Managed class, but use 256 -bit, 384-bit, and 51 2-bit hash codes, respectively Each of these algorithms uses a secret key that must be included each time the hash is generated against the same... "Bob/password: " & _ EncryptPassword("Bob", "password")) Project | 317 This code generated the following message: Alice/none: Alice/password: Bob/none: Bob/password: 657 0FC214A797C023F40 4AEC6C914C65D88BD082 7F544120E3AB9FB48C32 274A56F047293EA0B97E Undoing Some Previous Changes The UserName, GroupName, and GroupActivity tables in the database define the security profiles for each administrative user... source code of the form, and if this is how you want to design the inherited form, that’s fine But you and I are looking for simplicity in programming, and we plunked down good money for Visual Studio, so we’re certainly going to use its visual tools to edit our visual forms 318 | Chapter 11: Security The upshot of all this ranting—and I’m almost at the end of my rant, but you can keep going on if you... MACTripleDES class The secret key used in the calculation is either 16 or 24 bytes long, and the generated value is 8 bytes in length • Message-Digest algorithm number 5 (MD5) hash calculation, made available through the MD5CryptoServiceProvider class MD5 is yet another super-secret algorithm designed by Ron Rivest (that guy is amazing), but it has been shown to contain some flaws that could make it an encoding... convert the result into readable ASCII characters so that things wouldn’t look all weird when I issued SQL statements against the UserName table My conversion is basic: convert each byte into its printable hexadecimal equivalent using Visual Basic s Hex function Then just string the results together The UserName Password field holds only 20 characters, so I chop off anything longer Just to make sure... designed the code for BaseCodeForm.vb in Chapter 8, my goal was to show you the MustInherit and MustOverride class features included with Visual Basic They are pretty useful features Unfortunately, they just don’t mix well with user interface elements, and here’s why: Visual Studio actually creates instances of your forms at design time so that you can interact with them inside the editor If you were... let you similarly enhance classes, even if you don’t have access to the original source code for those classes What Is Operator Overloading? Operator overloading allows your code to enhance the basic Visual Basic operators, and endow them with abilities not previously granted to them by the compiler Overloading doesn’t change the syntax used when employing operators, but it does change the types of... The problem—and problem is putting it mildly—is that Visual Studio won’t (actually, can’t) create an instance of a class defined as MustInherit That’s because you must inherit it through another class first before you create instances What does this mean to you? It means that if you try to design a form that inherits from a MustInherit form template, Visual Studio will not present the user interface portion... symmetric encryption algorithms: • Data Encryption Standard (DES), a 56 -bit block cipher with primary support through the DESCryptoServiceProvider class This algorithm is generally secure, but due to its small key size (smaller keys are more easily compromised), it is inappropriate for highly sensitive data • RC2 (Rivest Cipher number 2), a 56 -bit block cipher with primary support through the RC2CryptoServiceProvider . 8 bytes in length. • Message-Digest algorithm number 5 (MD5) hash calculation, made available through the MD5CryptoServiceProvider class. MD5 is yet another super-secret algorithm designed by. 160-bit hash code. • Three other classes— SHA 256 Managed, SHA384Managed, and SHA512Managed—are similar to the SHA1Managed class, but use 256 -bit, 384-bit, and 51 2-bit hash codes, respectively. Each of. several of the important .NET namespaces, such as System, System.Windows.Forms, and Microsoft.VisualBasic. However, it doesn’t yet reference any of the ADO.NET namespaces. (Recall that “referencing”

Ngày đăng: 13/08/2014, 08:20

Từ khóa liên quan

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan