- •Table of Contents
- •Preface
- •What is ASP.NET?
- •Installing the Required Software
- •Installing the Web Server
- •Installing Internet Information Services (IIS)
- •Installing Cassini
- •Installing the .NET Framework and the SDK
- •Installing the .NET Framework
- •Installing the SDK
- •Configuring the Web Server
- •Configuring IIS
- •Configuring Cassini
- •Where do I Put my Files?
- •Using localhost
- •Virtual Directories
- •Using Cassini
- •Installing SQL Server 2005 Express Edition
- •Installing SQL Server Management Studio Express
- •Installing Visual Web Developer 2005
- •Writing your First ASP.NET Page
- •Getting Help
- •Summary
- •ASP.NET Basics
- •ASP.NET Page Structure
- •Directives
- •Code Declaration Blocks
- •Comments in VB and C# Code
- •Code Render Blocks
- •ASP.NET Server Controls
- •Server-side Comments
- •Literal Text and HTML Tags
- •View State
- •Working with Directives
- •ASP.NET Languages
- •Visual Basic
- •Summary
- •VB and C# Programming Basics
- •Programming Basics
- •Control Events and Subroutines
- •Page Events
- •Variables and Variable Declaration
- •Arrays
- •Functions
- •Operators
- •Breaking Long Lines of Code
- •Conditional Logic
- •Loops
- •Object Oriented Programming Concepts
- •Objects and Classes
- •Properties
- •Methods
- •Classes
- •Constructors
- •Scope
- •Events
- •Understanding Inheritance
- •Objects In .NET
- •Namespaces
- •Using Code-behind Files
- •Summary
- •Constructing ASP.NET Web Pages
- •Web Forms
- •HTML Server Controls
- •Using the HTML Server Controls
- •Web Server Controls
- •Standard Web Server Controls
- •Label
- •Literal
- •TextBox
- •HiddenField
- •Button
- •ImageButton
- •LinkButton
- •HyperLink
- •CheckBox
- •RadioButton
- •Image
- •ImageMap
- •PlaceHolder
- •Panel
- •List Controls
- •DropDownList
- •ListBox
- •RadioButtonList
- •CheckBoxList
- •BulletedList
- •Advanced Controls
- •Calendar
- •AdRotator
- •TreeView
- •SiteMapPath
- •Menu
- •MultiView
- •Wizard
- •FileUpload
- •Web User Controls
- •Creating a Web User Control
- •Using the Web User Control
- •Master Pages
- •Using Cascading Style Sheets (CSS)
- •Types of Styles and Style Sheets
- •Style Properties
- •The CssClass Property
- •Summary
- •Building Web Applications
- •Introducing the Dorknozzle Project
- •Using Visual Web Developer
- •Meeting the Features
- •The Solution Explorer
- •The Web Forms Designer
- •The Code Editor
- •IntelliSense
- •The Toolbox
- •The Properties Window
- •Executing your Project
- •Using Visual Web Developer’s Built-in Web Server
- •Using IIS
- •Using IIS with Visual Web Developer
- •Core Web Application Features
- •Web.config
- •Global.asax
- •Using Application State
- •Working with User Sessions
- •Using the Cache Object
- •Using Cookies
- •Starting the Dorknozzle Project
- •Preparing the Sitemap
- •Using Themes, Skins, and Styles
- •Creating a New Theme Folder
- •Creating a New Style Sheet
- •Styling Web Server Controls
- •Adding a Skin
- •Applying the Theme
- •Building the Master Page
- •Using the Master Page
- •Extending Dorknozzle
- •Debugging and Error Handling
- •Debugging with Visual Web Developer
- •Other Kinds of Errors
- •Custom Errors
- •Handling Exceptions Locally
- •Summary
- •Using the Validation Controls
- •Enforcing Validation on the Server
- •Using Validation Controls
- •RequiredFieldValidator
- •CompareValidator
- •RangeValidator
- •ValidationSummary
- •RegularExpressionValidator
- •Some Useful Regular Expressions
- •CustomValidator
- •Validation Groups
- •Updating Dorknozzle
- •Summary
- •What is a Database?
- •Creating your First Database
- •Creating a New Database Using Visual Web Developer
- •Creating Database Tables
- •Data Types
- •Column Properties
- •Primary Keys
- •Creating the Employees Table
- •Creating the Remaining Tables
- •Executing SQL Scripts
- •Populating the Data Tables
- •Relational Database Design Concepts
- •Foreign Keys
- •Using Database Diagrams
- •Diagrams and Table Relationships
- •One-to-one Relationships
- •One-to-many Relationships
- •Many-to-many Relationships
- •Summary
- •Speaking SQL
- •Reading Data from a Single Table
- •Using the SELECT Statement
- •Selecting Certain Fields
- •Selecting Unique Data with DISTINCT
- •Row Filtering with WHERE
- •Selecting Ranges of Values with BETWEEN
- •Matching Patterns with LIKE
- •Using the IN Operator
- •Sorting Results Using ORDER BY
- •Limiting the Number of Results with TOP
- •Reading Data from Multiple Tables
- •Subqueries
- •Table Joins
- •Expressions and Operators
- •Transact-SQL Functions
- •Arithmetic Functions
- •String Functions
- •Date and Time Functions
- •Working with Groups of Values
- •The COUNT Function
- •Grouping Records Using GROUP BY
- •Filtering Groups Using HAVING
- •The SUM, AVG, MIN, and MAX Functions
- •Updating Existing Data
- •The INSERT Statement
- •The UPDATE Statement
- •The DELETE Statement
- •Stored Procedures
- •Summary
- •Introducing ADO.NET
- •Importing the SqlClient Namespace
- •Defining the Database Connection
- •Preparing the Command
- •Executing the Command
- •Setting up Database Authentication
- •Reading the Data
- •Using Parameters with Queries
- •Bulletproofing Data Access Code
- •Using the Repeater Control
- •More Data Binding
- •Inserting Records
- •Updating Records
- •Deleting Records
- •Using Stored Procedures
- •Summary
- •DataList Basics
- •Handling DataList Events
- •Editing DataList Items and Using Templates
- •DataList and Visual Web Developer
- •Styling the DataList
- •Summary
- •Using the GridView Control
- •Customizing the GridView Columns
- •Styling the GridView with Templates, Skins, and CSS
- •Selecting Grid Records
- •Using the DetailsView Control
- •Styling the DetailsView
- •GridView and DetailsView Events
- •Entering Edit Mode
- •Using Templates
- •Updating DetailsView Records
- •Summary
- •Advanced Data Access
- •Using Data Source Controls
- •Binding the GridView to a SqlDataSource
- •Binding the DetailsView to a SqlDataSource
- •Displaying Lists in DetailsView
- •More on SqlDataSource
- •Working with Data Sets and Data Tables
- •What is a Data Set Made From?
- •Binding DataSets to Controls
- •Implementing Paging
- •Storing Data Sets in View State
- •Implementing Sorting
- •Filtering Data
- •Updating a Database from a Modified DataSet
- •Summary
- •Security and User Authentication
- •Basic Security Guidelines
- •Securing ASP.NET 2.0 Applications
- •Working with Forms Authentication
- •Authenticating Users
- •Working with Hard-coded User Accounts
- •Configuring Forms Authentication
- •Configuring Forms Authorization
- •Storing Users in Web.config
- •Hashing Passwords
- •Logging Users Out
- •ASP.NET 2.0 Memberships and Roles
- •Creating the Membership Data Structures
- •Using your Database to Store Membership Data
- •Using the ASP.NET Web Site Configuration Tool
- •Creating Users and Roles
- •Changing Password Strength Requirements
- •Securing your Web Application
- •Using the ASP.NET Login Controls
- •Authenticating Users
- •Customizing User Display
- •Summary
- •Working with Files and Email
- •Writing and Reading Text Files
- •Setting Up Security
- •Writing Content to a Text File
- •Reading Content from a Text File
- •Accessing Directories and Directory Information
- •Working with Directory and File Paths
- •Uploading Files
- •Sending Email with ASP.NET
- •Configuring the SMTP Server
- •Sending a Test Email
- •Creating the Company Newsletter Page
- •Summary
- •The WebControl Class
- •Properties
- •Methods
- •Standard Web Controls
- •AdRotator
- •Properties
- •Events
- •BulletedList
- •Properties
- •Events
- •Button
- •Properties
- •Events
- •Calendar
- •Properties
- •Events
- •CheckBox
- •Properties
- •Events
- •CheckBoxList
- •Properties
- •Events
- •DropDownList
- •Properties
- •Events
- •FileUpload
- •Properties
- •Methods
- •HiddenField
- •Properties
- •HyperLink
- •Properties
- •Image
- •Properties
- •ImageButton
- •Properties
- •Events
- •ImageMap
- •Properties
- •Events
- •Label
- •Properties
- •LinkButton
- •Properties
- •Events
- •ListBox
- •Properties
- •Events
- •Literal
- •Properties
- •MultiView
- •Properties
- •Methods
- •Events
- •Panel
- •Properties
- •PlaceHolder
- •Properties
- •RadioButton
- •Properties
- •Events
- •RadioButtonList
- •Properties
- •Events
- •TextBox
- •Properties
- •Events
- •Properties
- •Validation Controls
- •CompareValidator
- •Properties
- •Methods
- •CustomValidator
- •Methods
- •Events
- •RangeValidator
- •Properties
- •Methods
- •RegularExpressionValidator
- •Properties
- •Methods
- •RequiredFieldValidator
- •Properties
- •Methods
- •ValidationSummary
- •Properties
- •Navigation Web Controls
- •SiteMapPath
- •Properties
- •Methods
- •Events
- •Menu
- •Properties
- •Methods
- •Events
- •TreeView
- •Properties
- •Methods
- •Events
- •HTML Server Controls
- •HtmlAnchor Control
- •Properties
- •Events
- •HtmlButton Control
- •Properties
- •Events
- •HtmlForm Control
- •Properties
- •HtmlGeneric Control
- •Properties
- •HtmlImage Control
- •Properties
- •HtmlInputButton Control
- •Properties
- •Events
- •HtmlInputCheckBox Control
- •Properties
- •Events
- •HtmlInputFile Control
- •Properties
- •HtmlInputHidden Control
- •Properties
- •HtmlInputImage Control
- •Properties
- •Events
- •HtmlInputRadioButton Control
- •Properties
- •Events
- •HtmlInputText Control
- •Properties
- •Events
- •HtmlSelect Control
- •Properties
- •Events
- •HtmlTable Control
- •Properties
- •HtmlTableCell Control
- •Properties
- •HtmlTableRow Control
- •Properties
- •HtmlTextArea Control
- •Properties
- •Events
- •Index
Chapter 7: Database Design and Development
will contain a field that should only accept values from a specific list, it makes sense to create a table to hold that list. This approach makes it easy to execute changes to the list in future; it also reduces the amount of disk space required by your database, and helps you to avoid redundancy, as you store only single instances of department names, strings like “I can’t print,” and so on.
This process of planning out the entities, tables, and relationships between the tables to eliminate maintenance problems and redundant data is called database normalization. Although I’ll speak a bit more about normalization before the end of this chapter, I’ll only ever discuss it in an informal, hands-on (i.e. nonrigorous) way. As any computer science major will tell you, database design is a serious area of research, with tested and mathematically provable principles that, while useful, are beyond the scope of this book. If you want more information on the topic, stop by DataModel.org1 for a list of good books, as well as several useful resources on the subject. In particular, check out the Rules of Normalization in the Data Modeling section of the site.2
So, we’ve got our list of tables. In the next section, we’ll look at the columns within those tables, and discuss how we can ascertain their characteristics. Although we won’t go over the creation of all the tables for the Dorknozzle database, we will create one as an example: the Employees table. Once you understand how to create a new table, you can create the rest of the tables for the Dorknozzle application in your own time, based on the descriptions I’ll provide. Or, if you prefer, you can simply grab the finished database from the code archive.
Once you’ve outlined all your tables, the next step is to decide what pieces of information will be included within those tables. For instance, you may want to include a first name, last name, phone number, address, city, state, zip code, and so on, for all employees in the Employees table. Let’s see how we can define these columns as we create the Employees table for the Dorknozzle database.
Data Types
One of the differences between logical design and physical design is that when we’re planning the database’s physical design, we have to deal with details such as data types. That’s right—as with the data we’re storing in our VB.NET and C# variables, the data we store in each of our tables’s columns has a particular data type.
1http://www.datamodel.org/
2http://www.datamodel.org/NormalizationRules.html
262
Data Types
SQL Server knows many data types—in fact, it knows too many to list here—but it’s worth our while to take a look at the most common ones. Below is a list of the common data types that we’ll use in this book:
int
Use the int data type when you need to store whole integers. This data type can store numbers from -2,147,483,648 to 2,147,483,647.
float
Use the float data type when you're working with very large numbers or very small numbers. float can be used for fractions, but they are prone to rounding errors.
money
The money data type should be used to store monetary data, such as prices for a product catalog. This data type is closely related to the int data type.
bit
Use the bit data type when a condition is either true (represented as 1) or false (represented as 0).
datetime
As you might have guessed, the datetime data type is used to store dates and times. It’s very useful when you want to sort items in your table chronologically.
nvarchar(n)
The nvarchar data type stores strings of text. This is most commonly used data type because it stores names, descriptions, and the like. When defining a column of this type, we also need to specify a maximum size in parentheses; longer strings will be trimmed to fit the defined size. For example, nvarchar(50) specifies an field that can hold up to 50 characters. The var part of the nvarchar name comes from the fact that this data type can store strings of variable length up to the specified maximum.
nchar(n)
The nchar data type is similar to nvarchar in that it stores strings, but a field of this type will always store strings of the defined size. If the string you’re saving is shorter, it’s padded with spaces until the specified size is reached.
For example, if you’re working with an nchar(6) field (where the 6 in parentheses indicates that the field can hold six characters), and you add the word “test” to the field, two space characters will be appended to the end of the word so that all six characters are used. This type is useful when you’re storing
263
Chapter 7: Database Design and Development
strings that have a predefined size—in such cases, it may be more efficient to use the nchar(n) type than nvarchar.
money, money, money
Sometimes, you may see poorly designed databases use float to store monetary data. As float is susceptible to rounding errors, this is a bad idea. money, on the other hand, is not susceptible to these errors and is a much better choice.
The SQL Server data types, as with the other SQL Server keywords, aren’t casesensitive. nvarchar and nchar have non-Unicode cousins named varchar and char, which you can use if you’re sure you won’t need to store Unicode data. You may need to use Unicode (or a language-specific form of encoding) when storing nonEnglish text, such as Chinese, Arabic, and others. Unicode is a very widely supported standard, so it’s strongly recommended you stick with nvarchar and nchar.
The type of a column defines how that column behaves. For example, sorting data by a datetime column will cause the records to be sorted chronologically, rather than alphabetically or numerically.
Column Properties
Other than a column’s data type, we can define a number of other properties for a column. Other properties you’ll use frequently include:
NULL
In database speak, NULL means “undefined.” Although we talk about it as if it’s a value, NULL actually represents the lack of a value. If you set an employee’s mobile telephone number to NULL, for example, this could represent the fact that the employee doesn’t have a mobile telephone.
However, it’s important to realize that allowing NULLs is often inappropriate. For instance, you might create a department with the name NULL to represent a mysterious department with no name, but obviously, this is far from ideal. As you create a table, you can specify which columns are allowed to store NULL, and which aren’t. In our example, we’d like every department to have a name, so we shouldn’t allow the Name column to allow NULLs.
DEFAULT
SQL Server is capable of supplying a default value for a certain column if you don’t supply one when you add a new row. We won’t be using this feature when we create Dorknozzle, but it’s good to know you have this option.
264
Primary Keys
IDENTITY
Identity columns are numbered automatically. If you set a column as an IDENTITY column, SQL Server will generate numbers automatically for that column as you add new rows to it. The first number in the column is called the identity seed. To generate subsequent numbers, the identity column adds a given value to the seed; the value that’s added is called the identity increment. By default, both the seed and increment have a value of 1, in which case the generated values are 1, 2, 3, and so on. If the identity seed were 5 and the identity increment were 10, the generated numbers would be 5, 15, 25, and so on.
IDENTITY is useful for ID columns, such as Department ID, for which you don’t care what the values are, as long as they’re unique. When you use IDENTITY, the generated values will always be unique. By default, you can’t specify values for an IDENTITY column. Note also that the column can never contain NULL.
Understanding NULL
Be sure not to see NULL as equivalent to 0 (in numerical columns), or an empty string (in the case of string columns). Both 0 and an empty string are values; NULL defines the lack of a value.
NULL and Default Values
I’ve often heard people say that when we set a default value for a column, it doesn’t matter whether or not we set it to accept NULLs. Many people seem to believe that columns with default values won’t store NULL.
That’s incorrect. You can modify a record after it was created, and change any field that will allow it to NULL. Your columns’ ability to store NULL is important for the integrity of your data, and it should reflect the purpose of that data. A default value does make things easier when we create new rows, but it’s not as vital as is correctly allowing (or disallowing) NULL in columns.
Primary Keys
Primary keys are the last fundamental concept that you need to understand before you can create your first data table. In the world of relational databases, each row in a table must be identified uniquely by a column called a key, on which all database operations are based.
265
Chapter 7: Database Design and Development
The tables in your databases could contain hundreds or even thousands of rows of similar data—you could have several hundred employees in your Employees table alone. Imagine that your program needs to update or delete the record for John Smith, and there are several people with that name in your organization. You couldn’t rely on the database to find the record for the particular John Smith that you were trying to work with—it might end up updating or deleting the wrong record.
We can avoid these kinds of problems only by using a system that uniquely identifies each row in the table. The first step toward achieving this goal is to add to the table an ID column that provides a unique for each employee, as did the Employee ID column that we saw in Figure 7.1.
Remember that when we discussed this Employees table, we noted that you may be tempted to use each employee’s username to uniquely identify each employee. After all, that’s what the network administrator uses them for, so why shouldn’t you? It’s true that this column uniquely identifies each row in the table, and we call such a column a candidate key. However, it wouldn’t be a good idea to use this column in our database operations for a number of reasons. Firstly, network usernames have been known to change, and such a change would wreak havoc on any database of more than a couple of tables. As we’ll see later, keys are fundamental to establishing relationships between tables, and these relationships rely on the fact that keys will never change. Secondly, non-numeric keys require much more processing power than simple numeric ones. Using an nvarchar field to uniquely identify rows in your table will bring your SQL Server to a grinding halt much, much quicker than if you chose a simple, numeric key.
The column that we choose to uniquely identify a row in a table in practice is called the primary key. In the case of our Employee table, the Employee ID will always be unique, so it would be a suitable primary key.
Multi-column Keys
To make the concept of keys easier to understand, we kept the definition simple, although it’s not 100% technically correct. A key isn’t necessarily formed by a single column—it can be formed by two or more columns. If the key is made up of multiple columns, the set of values in those columns must be unique for any given record. We’ll see an example of such a key in a moment.
Although we usually refer to primary keys as if they were columns, technically they are constraints that we apply to the existing columns of a table. Constraints impose restrictions on the data we can enter into our tables, and the primary key
266