- •Using Your Sybex Electronic Book
- •Acknowledgments
- •Contents at a Glance
- •Introduction
- •Who Should Read This Book?
- •How About the Advanced Topics?
- •The Structure of the Book
- •How to Reach the Author
- •The Integrated Development Environment
- •The Start Page
- •Project Types
- •Your First VB Application
- •Making the Application More Robust
- •Making the Application More User-Friendly
- •The IDE Components
- •The IDE Menu
- •The Toolbox Window
- •The Solution Explorer
- •The Properties Window
- •The Output Window
- •The Command Window
- •The Task List Window
- •Environment Options
- •A Few Common Properties
- •A Few Common Events
- •A Few Common Methods
- •Building a Console Application
- •Summary
- •Building a Loan Calculator
- •How the Loan Application Works
- •Designing the User Interface
- •Programming the Loan Application
- •Validating the Data
- •Building a Math Calculator
- •Designing the User Interface
- •Programming the MathCalculator App
- •Adding More Features
- •Exception Handling
- •Taking the LoanCalculator to the Web
- •Working with Multiple Forms
- •Working with Multiple Projects
- •Executable Files
- •Distributing an Application
- •VB.NET at Work: Creating a Windows Installer
- •Finishing the Windows Installer
- •Running the Windows Installer
- •Verifying the Installation
- •Summary
- •Variables
- •Declaring Variables
- •Types of Variables
- •Converting Variable Types
- •User-Defined Data Types
- •Examining Variable Types
- •Why Declare Variables?
- •A Variable’s Scope
- •The Lifetime of a Variable
- •Constants
- •Arrays
- •Declaring Arrays
- •Initializing Arrays
- •Array Limits
- •Multidimensional Arrays
- •Dynamic Arrays
- •Arrays of Arrays
- •Variables as Objects
- •So, What’s an Object?
- •Formatting Numbers
- •Formatting Dates
- •Flow-Control Statements
- •Test Structures
- •Loop Structures
- •Nested Control Structures
- •The Exit Statement
- •Summary
- •Modular Coding
- •Subroutines
- •Functions
- •Arguments
- •Argument-Passing Mechanisms
- •Event-Handler Arguments
- •Passing an Unknown Number of Arguments
- •Named Arguments
- •More Types of Function Return Values
- •Overloading Functions
- •Summary
- •The Appearance of Forms
- •Properties of the Form Control
- •Placing Controls on Forms
- •Setting the TabOrder
- •VB.NET at Work: The Contacts Project
- •Anchoring and Docking
- •Loading and Showing Forms
- •The Startup Form
- •Controlling One Form from within Another
- •Forms vs. Dialog Boxes
- •VB.NET at Work: The MultipleForms Project
- •Designing Menus
- •The Menu Editor
- •Manipulating Menus at Runtime
- •Building Dynamic Forms at Runtime
- •The Form.Controls Collection
- •VB.NET at Work: The DynamicForm Project
- •Creating Event Handlers at Runtime
- •Summary
- •The TextBox Control
- •Basic Properties
- •Text-Manipulation Properties
- •Text-Selection Properties
- •Text-Selection Methods
- •Undoing Edits
- •VB.NET at Work: The TextPad Project
- •Capturing Keystrokes
- •The ListBox, CheckedListBox, and ComboBox Controls
- •Basic Properties
- •The Items Collection
- •VB.NET at Work: The ListDemo Project
- •Searching
- •The ComboBox Control
- •The ScrollBar and TrackBar Controls
- •The ScrollBar Control
- •The TrackBar Control
- •Summary
- •The Common Dialog Controls
- •Using the Common Dialog Controls
- •The Color Dialog Box
- •The Font Dialog Box
- •The Open and Save As Dialog Boxes
- •The Print Dialog Box
- •The RichTextBox Control
- •The RTF Language
- •Methods
- •Advanced Editing Features
- •Cutting and Pasting
- •Searching in a RichTextBox Control
- •Formatting URLs
- •VB.NET at Work: The RTFPad Project
- •Summary
- •What Is a Class?
- •Building the Minimal Class
- •Adding Code to the Minimal Class
- •Property Procedures
- •Customizing Default Members
- •Custom Enumerations
- •Using the SimpleClass in Other Projects
- •Firing Events
- •Shared Properties
- •Parsing a Filename String
- •Reusing the StringTools Class
- •Encapsulation and Abstraction
- •Inheritance
- •Inheriting Existing Classes
- •Polymorphism
- •The Shape Class
- •Object Constructors and Destructors
- •Instance and Shared Methods
- •Who Can Inherit What?
- •Parent Class Keywords
- •Derived Class Keyword
- •Parent Class Member Keywords
- •Derived Class Member Keyword
- •MyBase and MyClass
- •Summary
- •On Designing Windows Controls
- •Enhancing Existing Controls
- •Building the FocusedTextBox Control
- •Building Compound Controls
- •VB.NET at Work: The ColorEdit Control
- •VB.NET at Work: The Label3D Control
- •Raising Events
- •Using the Custom Control in Other Projects
- •VB.NET at Work: The Alarm Control
- •Designing Irregularly Shaped Controls
- •Designing Owner-Drawn Menus
- •Designing Owner-Drawn ListBox Controls
- •Using ActiveX Controls
- •Summary
- •Programming Word
- •Objects That Represent Text
- •The Documents Collection and the Document Object
- •Spell-Checking Documents
- •Programming Excel
- •The Worksheets Collection and the Worksheet Object
- •The Range Object
- •Using Excel as a Math Parser
- •Programming Outlook
- •Retrieving Information
- •Recursive Scanning of the Contacts Folder
- •Summary
- •Advanced Array Topics
- •Sorting Arrays
- •Searching Arrays
- •Other Array Operations
- •Array Limitations
- •The ArrayList Collection
- •Creating an ArrayList
- •Adding and Removing Items
- •The HashTable Collection
- •VB.NET at Work: The WordFrequencies Project
- •The SortedList Class
- •The IEnumerator and IComparer Interfaces
- •Enumerating Collections
- •Custom Sorting
- •Custom Sorting of a SortedList
- •The Serialization Class
- •Serializing Individual Objects
- •Serializing a Collection
- •Deserializing Objects
- •Summary
- •Handling Strings and Characters
- •The Char Class
- •The String Class
- •The StringBuilder Class
- •VB.NET at Work: The StringReversal Project
- •VB.NET at Work: The CountWords Project
- •Handling Dates
- •The DateTime Class
- •The TimeSpan Class
- •VB.NET at Work: Timing Operations
- •Summary
- •Accessing Folders and Files
- •The Directory Class
- •The File Class
- •The DirectoryInfo Class
- •The FileInfo Class
- •The Path Class
- •VB.NET at Work: The CustomExplorer Project
- •Accessing Files
- •The FileStream Object
- •The StreamWriter Object
- •The StreamReader Object
- •Sending Data to a File
- •The BinaryWriter Object
- •The BinaryReader Object
- •VB.NET at Work: The RecordSave Project
- •The FileSystemWatcher Component
- •Properties
- •Events
- •VB.NET at Work: The FileSystemWatcher Project
- •Summary
- •Displaying Images
- •The Image Object
- •Exchanging Images through the Clipboard
- •Drawing with GDI+
- •The Basic Drawing Objects
- •Drawing Shapes
- •Drawing Methods
- •Gradients
- •Coordinate Transformations
- •Specifying Transformations
- •VB.NET at Work: Plotting Functions
- •Bitmaps
- •Specifying Colors
- •Defining Colors
- •Processing Bitmaps
- •Summary
- •The Printing Objects
- •PrintDocument
- •PrintDialog
- •PageSetupDialog
- •PrintPreviewDialog
- •PrintPreviewControl
- •Printer and Page Properties
- •Page Geometry
- •Printing Examples
- •Printing Tabular Data
- •Printing Plain Text
- •Printing Bitmaps
- •Using the PrintPreviewControl
- •Summary
- •Examining the Advanced Controls
- •How Tree Structures Work
- •The ImageList Control
- •The TreeView Control
- •Adding New Items at Design Time
- •Adding New Items at Runtime
- •Assigning Images to Nodes
- •Scanning the TreeView Control
- •The ListView Control
- •The Columns Collection
- •The ListItem Object
- •The Items Collection
- •The SubItems Collection
- •Summary
- •Types of Errors
- •Design-Time Errors
- •Runtime Errors
- •Logic Errors
- •Exceptions and Structured Exception Handling
- •Studying an Exception
- •Getting a Handle on this Exception
- •Finally (!)
- •Customizing Exception Handling
- •Throwing Your Own Exceptions
- •Debugging
- •Breakpoints
- •Stepping Through
- •The Local and Watch Windows
- •Summary
- •Basic Concepts
- •Recursion in Real Life
- •A Simple Example
- •Recursion by Mistake
- •Scanning Folders Recursively
- •Describing a Recursive Procedure
- •Translating the Description to Code
- •The Stack Mechanism
- •Stack Defined
- •Recursive Programming and the Stack
- •Passing Arguments through the Stack
- •Special Issues in Recursive Programming
- •Knowing When to Use Recursive Programming
- •Summary
- •MDI Applications: The Basics
- •Building an MDI Application
- •Built-In Capabilities of MDI Applications
- •Accessing Child Forms
- •Ending an MDI Application
- •A Scrollable PictureBox
- •Summary
- •What Is a Database?
- •Relational Databases
- •Exploring the Northwind Database
- •Exploring the Pubs Database
- •Understanding Relations
- •The Server Explorer
- •Working with Tables
- •Relationships, Indices, and Constraints
- •Structured Query Language
- •Executing SQL Statements
- •Selection Queries
- •Calculated Fields
- •SQL Joins
- •Action Queries
- •The Query Builder
- •The Query Builder Interface
- •SQL at Work: Calculating Sums
- •SQL at Work: Counting Rows
- •Limiting the Selection
- •Parameterized Queries
- •Calculated Columns
- •Specifying Left, Right, and Inner Joins
- •Stored Procedures
- •Summary
- •How About XML?
- •Creating a DataSet
- •The DataGrid Control
- •Data Binding
- •VB.NET at Work: The ViewEditCustomers Project
- •Binding Complex Controls
- •Programming the DataAdapter Object
- •The Command Objects
- •The Command and DataReader Objects
- •VB.NET at Work: The DataReader Project
- •VB.NET at Work: The StoredProcedure Project
- •Summary
- •The Structure of a DataSet
- •Navigating the Tables of a DataSet
- •Updating DataSets
- •The DataForm Wizard
- •Handling Identity Fields
- •Transactions
- •Performing Update Operations
- •Updating Tables Manually
- •Building and Using Custom DataSets
- •Summary
- •An HTML Primer
- •HTML Code Elements
- •Server-Client Interaction
- •The Structure of HTML Documents
- •URLs and Hyperlinks
- •The Basic HTML Tags
- •Inserting Graphics
- •Tables
- •Forms and Controls
- •Processing Requests on the Server
- •Building a Web Application
- •Interacting with a Web Application
- •Maintaining State
- •The Web Controls
- •The ASP.NET Objects
- •The Page Object
- •The Response Object
- •The Request Object
- •The Server Object
- •Using Cookies
- •Handling Multiple Forms in Web Applications
- •Summary
- •The Data-Bound Web Controls
- •Simple Data Binding
- •Binding to DataSets
- •Is It a Grid, or a Table?
- •Getting Orders on the Web
- •The Forms of the ProductSearch Application
- •Paging Large DataSets
- •Customizing the Appearance of the DataGrid Control
- •Programming the Select Button
- •Summary
- •How to Serve the Web
- •Building a Web Service
- •Consuming the Web Service
- •Maintaining State in Web Services
- •A Data-Driven Web Service
- •Consuming the Products Web Service in VB
- •Summary
THE SERVER EXPLORER 883
in the U.S., you can set the Country’s default value the string “US” (without the quotes) so that users will supply another value only for customers from another country. The Collation setting determines how the rows will be sorted, as well as how the database will search for values in the specific column. Normally, you set a collation sequence when you set up the database. You can specify a different sort order for a specific field by setting its Collation property. If you click the button with the ellipses next to the Collation setting, you’ll see a large number of settings. The string “CS” and “CI” stand for case-sensitive and case-insensitive, respectively. Searches are usually case-insensitive, so that the argument “Mc Donald” will locate “MC Donald” and “Mc DONALD.” The strings “AS” and “AI” stand for accent-sensitive and accent-insensitive; they’re used with languages that recognize accent marks.
Numeric fields can be integers (data type int), big integers (data type bigint) and floating-point numbers (data type real), among others. As you can see, SQL Server’s data types are not named after VB’s data types, but they’re mapped to the corresponding data types of Visual Basic. The bigint data type is the same as a long integer in VB.
Integer data types have an Identity property: in each table you can have one identity field, which is an integer value. This value is incremented by the DBMS every time a new row is added, and it’s guaranteed to be unique. We use these fields as primary indices. The primary index is unique for each row and is used in establishing relations between tables. The actual value of no interest to users; they don’t even have to see this field. All you really want is that the primary key in one row has the same value as the foreign key(s) in the related table(s).
New Table
This command adds a new table to the database. If you select it, you will see a grid like the one shown back in Figure 20.8, only all rows will be empty. You can start adding fields by specifying a name, a data type, and its Allow Nulls property. For the purposes of this book, I will assume that the database has already been designed for you. Designing databases is no trivial tasks, and programmers shouldn’t be adding tables to simplify their code. We first organize our data into tables, create the tables, set up relations between them, and only then can we code against the database. It’s not uncommon to add a table to an existing database at a later stage, but this reveals some flaw in the initial database design.
Notice that once you add a table to the database, you can’t remove it through the Server Explorer. You must open the same database with the Enterprise Manager and delete it from there.
Relationships, Indices, and Constraints
To manipulate relationships, indices, and constraints, open one of the tables in design mode. Then right-click somewhere on the table and select Property Pages. There are four tabs on the property pages dialog box, one for each of the major objects of the database. The first tab, Tables, displays the name of the table you selected in the Server Explorer. Notice that you can’t select a different table on this dialog box.
Relationships Tab
The second tab, Relationships, is where you can specify relationships between tables (Figure 20.9). Select the Property Pages of the Categories table and you will see that there is already a relationship between the Categories table and the Products table. The relationship is called FK_Products_Categories,
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
884 Chapter 20 DATABASES: ARCHITECTURE AND BASIC CONCEPTS
and it relates the primary and foreign keys of the two tables (field CategoryID). The names of the two related tables appear in two read-only boxes. When you create a new relationship, you’ll be able to select a table from a drop-down list. Under each table’s name, you see a list of fields. Here you select the matching fields in the two tables. Most relationships are based on a single field, which is common to both tables. However, you can relate two tables on multiple fields (you may have to use relationships based on multiple fields in an accounting application). The check boxes at the bottom of the page specify how the DBMS will handle the relationship and are discussed shortly.
Figure 20.9
The Relationships tab on the table’s property pages
To create a new relationship with another table, click the New button. A new relationship will be added with a default name, which you can change. Like all other objects, relationships have unique names too.
Expand the Primary Key Table box and select the name of the table with the primary key in the relationship. Then expand the Foreign Key Table box and select the name of the other table. The relationship’s name will change to reflect the selected tables. The default relationship names
starts with the string “FK” (which stands for foreign key), followed by an underscore character and the name of the foreign table, followed by another underscore and the name of the primary table. You can change the relationship’s name to anything you like.
If the relationship is based on a compound key, select all the fields that make up the primary and foreign keys, in the same order. At the bottom of the Properties window, you see a few options that you can set or clear:
Check existing data on creation If the existing data violate the relationship, the new relationship won’t be established. You will have to fix the data and then attempt to establish the relationship again.
Enforce relationship for replication The relationship is enforced when the database is replicated.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
THE SERVER EXPLORER 885
Enforce relationship for INSERTs and UPDATEs The relationship is enforced when you add new data or update existing data. If you attempt to add data that violate the relationship, the new data (or the update) will be rejected. SQL Server won’t let you enter data that violate the relationship between two tables, and this option should be checked (except for rare occasions).
Cascade update related fields When you change the primary key in one table, some rows of a related table will be left with an invalid foreign key. If you change the ID of a publisher, for example, all the titles that pointed to this publisher will become invalid after you change the publisher’s ID. If this option is checked, SQL Server will change the foreign key of the related tables as well.
Cascade delete related records When you delete the primary key in one table, some rows of a related table will be left with an invalid foreign key. If you delete a publisher, for example, all the titles that pointed to this publisher will become invalid after the deletion of the publisher. If this option is checked, SQL Server will delete all the rows of the related table(s) with the same foreign key.
You can also establish a relationship between two tables on the database diagram with point-and- click operations. Figure 20.2 shows a database diagram that relates the Products table to the Suppliers table. With the database diagram, you can easily visualize how the tables are organized in the database. Relationships are depicted as lines connecting two tables, and you can easily figure out which is the primary table (the line that connects the two tables has the symbol of a key to the end of the primary table) and which is the foreign table (the same line has the infinity symbol at the foreign table).
The Northwind database doesn’t include any database diagrams, so you must create one. To add a diagram to a database, right-click the Diagrams item and, from the context menu, select New Diagram. You can do the same in the Enterprise Manager, if you prefer.
As soon as you select the New Diagram command, you’ll be prompted to select the names of the tables to be added to the diagram through the Add Table dialog box. Select the first table you want to add to the diagram and click the Add button. Repeat the same process for all the tables
you want to include in the diagram, and then click the Close button. A very simple diagram could include the Products, Categories, and Suppliers tables. The first two tables are related through the CategoryID field, and the latter two through the SupplierID field. Select the three tables and click the Add button to add them to the diagram. On the next screen, click the Close button to close the dialog.
This will create a new diagram and place the links between the tables. All you have to do is rearrange the tables a little on the diagram pane, so that you can easily visualize them, along with their relationships. Since the relationships between the tables exist already, it will also draw the lines between the tables. Each table on the diagram is represented by a box that contains all the fields in the corresponding table. Primary key fields are marked with the symbol of a key. Figure 20.10 shows how a database diagram depicts the relationship between the Products & Categories tables and the relationship between the Products & Suppliers tables. Close the Database Diagram window and you’ll be prompted to enter a name for the diagram (name it Products).
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
886 Chapter 20 DATABASES: ARCHITECTURE AND BASIC CONCEPTS
Figure 20.10
A database diagram created with SQL Server’s Enterprise Manager
The most common relationships are one-to-many relationships, just like the ones shown in Figure 20.10. They’re called one-to-many because each primary key may appear in multiple rows of the foreign table. Each category ID appears in multiple rows of the Products table. Likewise, each supplier’s ID may also appear in multiple rows of the Products table—but a primary key is unique in its table.
To view or edit the details of a relationship, right-click the line that represents the relationship and you will see the following commands:
Delete relationship from database This command removes the relationship between the two tables.
Property Pages This command will bring up the property pages of the primary table, where you can specify additional relationships or constraints.
Earlier in this chapter, you saw that you couldn’t remove a row from the Categories table, because this action conflicted with the FK_Products_Categories constraint. If you open the first diagram you created in this section and examine the properties of the relation between the Product and Categories tables, you’ll see that its name is FK_Products_Categories and that the relation is enforced. If you want to be able to delete Categories, you must delete all the products that are connected to the specific category first. SQL Server can take care of deleting the related rows for you, if you check Cascade Delete Related Records. This is a rather dangerous practice, and you shouldn’t check it without good reason. For the case of the Products table, you shouldn’t enable cascade deletions. The products are also linked to the Order Details table, which means that the corresponding detail lines would also disappear from the database. Allowing cascade deletion in a database like Northwind will result in loss of valuable information irrevocably.
There are other situations where cascade deletion is not such a critical issue. You can enable cascade deletions in the Pubs database, for instance, so that each time you delete a title, the corresponding rows in the TitleAuthor table will also be removed. When you delete a book, you obviously don’t need any information about this book in the TitleAuthor table. If you insert the same book into the database again, you may use a different ID and the old links to the Authors table will not work—you’ll have to link the new title to its author(s) again anyway.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
THE SERVER EXPLORER 887
Indexes/Keys Tab
You’ve created a few tables and have actually entered some data into them. Now the most important thing you can do with a database is extract data from it (or else, why store the information in the first place?). We rarely browse the rows of a single table. Instead, we’re interested in summary information that will help us make business decisions. We need answers to questions like “What’s the most popular product in California?” or “What month has the largest sales for a spe-
cific product?” To retrieve this type of information, you must combine multiple tables. To answer the first question, you must locate all the customers in California, retrieve their orders, sum the quantities of the items they have purchased, and then select the product with the largest sum
of quantities. As you can guess, a DBMS must be able to scan the tables and locate the desired rows quickly.
Computers use a special technique, called indexing, to locate information very quickly. This technique requires that the data be maintained in some order. The indexed rows need not be in a specific physical order, as long as we can retrieve them in a specific order. If you want to retrieve the name of the category of a specific product, the rows of the Categories table must be ordered according to the CategoryID field. This is the value that links each row in the Products table to the corresponding row in the Categories table. The DBMS will retrieve the CategoryID field of a specific product, and then it will instantly locate the matching row in the Categories table, because the rows of this table are indexed according to their CategoryID field.
Fortunately, you don’t have to maintain the rows of the tables in any order yourself. The DBMS does it for you. You simply specify that a table be maintained in a specific order according to a column’s value, and the DBMS will take over. The DBMS can maintain multiple indexes for the same table. You may wish to search the products by name and supplier. It’s customary to search for a customer by name, city, postal code, country, and so on. To speed up the searches, you can maintain an index for each field you want to search on.
Indexes are manipulated by the DBMS; all you have to do is define them. Every time a new row is added or an existing row is deleted or edited, the table’s indexes are automatically updated. You can use the index at any time to locate rows very quickly. Practically, indexes allow you to select a row based on an indexed field instantly. When searching for specific rows, the DBMS will take into consideration automatically any index that can speed the search.
Figure 20.11 shows the properties of the PK_Categories index of the Categories table. This index is based on the column CategoryID of the table, and it maintains the rows of the Categories table in ascending order according to their ID. The prefix PK stands for primary key. To specify that an index is also the table’s primary key, you must check the option Create Unique. You can create as many indices as necessary for each table, but only one of them can be the primary key. The Create Unique box in Figure 20.11 is disabled, because the primary key is involved in one or more relationships— therefore, you can’t change the table’s primary key because you’ll break some of the existing relationships with other tables. To create a new index, click the New button, specify the column on which the new index will be based, and then enter a name for the new index (or accept the default one). You can create an index that uses multiple fields, but there are no multifield indices in the sample databases.
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
888 Chapter 20 DATABASES: ARCHITECTURE AND BASIC CONCEPTS
Figure 20.11
The Indexes/Keys tab of the property pages
Check Constraints Tab
A constraint is another important object of a database. The entity represented by a field may be subject to physical constraints. The Discount field, for example, should be a positive value no greater than 1 (or 100, depending on how you want to store it). Prices are also positive values. Other fields are subject to more complicated constraints. The DBMS can make sure that the values assigned to those fields do not violate the constraints. Otherwise, you’d have to make sure that all the applications that access the same fields conform to the physical constraints.
Figure 20.12
The Check Constraints tab of the property pages
Copyright ©2002 SYBEX, Inc., Alameda, CA |
www.sybex.com |
