Section 10.3. Creating Data Objects by Hand


10.3. Creating Data Objects by Hand

In all of the examples so far, you have created the DataSet object and its DataTable and DataRow objects by selecting data from the database. There are, however, occasions when you will want to fill a dataset or a table by hand.

For example, you may want to gather data from a user , and push that data into the database. It can be convenient to add records to a table manually and update the database from that table.

The dataset is an excellent transport mechanism for data. You may even want to create a dataset by hand only to pass it to another tier in your application where it will be used as a data source.

In the next example, you will create a dataset and populate three tables by hand. Once the tables are created, you'll set constraints on a number of columns, set default values, establish identity columns , and create keys. In addition, you'll establish a foreign key relationship between two tables, and you'll create a data relation tying two tables together. It sounds like more work than it really is.

Figure 10-7. Details panel displayed

10.3.1. Bug Database Design

Rather than use the Northwind database for this exercise, you will create a database for tracking bugs in a software development project. Imagine that you have been asked to create a tool to manage bugs for a large development effort. You will be supporting three developers along with a user interface designer and a few quality control engineers . You would like your design to be reasonably flexible so you can reapply your bug tracking application to future projects.

Your first decision is to create a web application. This has the great advantage that all the participants will be able to access the application from their home computers. Since the developers work off-site, this is almost a necessity. You will, of course, develop your web application in ASP.NET.

There will be a web page for entering bugs, as well as a page for reviewing and editing bugs. To support this, you will need to design a relational database; we'll use SQL Server.

You begin by thinking about the kinds of information you want to capture in the database and how that information will be used. You will want to allow any user of the system to create a bug report. You'll also want certain users (such as developers and Quality Assurance, or QA) to update the bug reports . Developers will want to be able to record progress in fixing a bug or to mark a bug fixed. QA will want to check the fix and close the bug or reopen it for further investigation. The original reporter of the bug will want to find out who is working on the bug and track the progress.

One requirement imposed early in the design process is that the bug database ought to provide an audit trail. If the bug is modified, you'll want to be able to say who modified it and when they did so. In fact, you'll want to be able to track all the changes to the bug, so you can generate a report like the excerpt shown in Example 10-4.

Example 10-4. Excerpt from a bug report
 Bug 101 - System crashes on login 101.1 - Reporter: Osborn Date: 1/1/2002  Original bug filed Description: When I login I crash. Status: Open Owner: QA 101.2 - Modified by: Smith Date: 1/2/2002 Changed Status, Owner Action: Confirmed bug. Status: Assigned Owner: Hurwitz 101.3 - Modified by Hurwitz Date 1/2/2002 Changed Status Action: I'll look into this but I don't think it is my code. Status: Accepted Owner: Hurwitz 101.4 - Modified by Hurwitz Date 1/3/2002 Changed Status, Owner Action: Fault lies in login code. Reassigned to Liberty Status: Assigned Owner: Liberty 101.5 - Modified by Liberty Date: 1/3/2002 Changed Status Action: Yup, this is mine. Status: Accepted Owner: Liberty 101.6 - Modified by Liberty Date 1/4/2002 Changed Status, Owner Action: Added test for null loginID in DoLogin(  ) Status: Fixed Owner: QA 101.7 - Modified by Smith Date: 1/4/2002 Changed Status Action: Tested and confirmed Status: Closed Owner: QA 

To track this information, you'll need to know the date and time of each modification, who made the modification, and what they did. There will probably be other information you'll want to capture as well though this may become more obvious as you build the application and as you use it.

One way to meet these requirements is to create two tables to represent each bug. Each record in the Bugs table will represent a single bug, but you'll need an additional table to keep track of the revisions. Call this second table BugHistory.

A bug record will have a BugID and will include the information that is constant for the bug throughout its history. A BugHistory record will have the information specific to each revision.

The bug database design described in this chapter includes three significant tables: Bugs , BugHistory , and People . Bugs and BugHistory work together to track the progress of a bug. For any given bug, a single record is created in the Bugs table, and a record is created in BugHistory each time the bug is revised in any way. The People table tracks the developers, QA, and other personnel who might be referred to in a bug report. See the design diagram in Figure 10-8.

Figure 10-8. The relationship among the tables

This is a simplified design that meets the detailed specifications, but which focuses on the key technologies; a robust professional design would necessarily be more complex.


When a bug is first entered, a record is created in each of the Bugs and BugHistory tables. Each time the bug is updated, a record is added to BugHistory . During the evolution of a bug, the status, severity, and owner of a bug may change, but the initial description and reporter will not. Those items that are consistent for the entire bug are in the Bugs table; those that are updated as the bug is corrected are in the BugHistory table.

10.3.2. Creating the DataTable by Hand

Create a new web application named BugTrackerByHand. Drag two GridView objects onto the form. Name the first Bugs and the second BugConstraints . Use Auto Format to make them look reasonably nice. The ASPX page is shown in Example 10-5.

Example 10-5. BugTrackerbyhand Default.aspx
 <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs"    Inherits="_Default" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server">     <title>Bug Tracker</title> </head> <body>     <form id="form1" runat="server">     <div>         <asp:GridView ID="Bugs" runat="server"            CellPadding="4" ForeColor="#333333" GridLines="None">             <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />             <RowStyle BackColor="#EFF3FB" />             <PagerStyle BackColor="#2461BF" ForeColor="White"                 HorizontalAlign="Center" />             <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True"                 ForeColor="#333333" />             <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />             <EditRowStyle BackColor="#2461BF" />             <AlternatingRowStyle BackColor="White" />         </asp:GridView>         <asp:GridView ID="BugConstraints" runat="server"             BackColor="#DEBA84" BorderColor="#DEBA84"             BorderStyle="None" BorderWidth="1px" CellPadding="3" CellSpacing="2">             <FooterStyle BackColor="#F7DFB5" ForeColor="#8C4510" />             <RowStyle BackColor="#FFF7E7" ForeColor="#8C4510" />             <PagerStyle ForeColor="#8C4510" HorizontalAlign="Center" />             <SelectedRowStyle BackColor="#738A9C" Font-Bold="True"                 ForeColor="White" />             <HeaderStyle BackColor="#A55129" Font-Bold="True" ForeColor="White" />         </asp:GridView>     </div>     </form> </body> </html> 

The supporting code-behind is shown in Example 10-6 and analyzed immediately afterward.

Example 10-6. BugTrackerbyhand Default.aspx.cs
 using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; public partial class _Default : System.Web.UI.Page {     protected void Page_Load(object sender, EventArgs e)     {         if (!IsPostBack)         {             // call the method whichthat creates the tables and the relations             DataSet ds = CreateDataSet(  );             // set the data source for the grid to the first table             Bugs.DataSource = ds.Tables["Bugs"];             Bugs.DataBind(  );             BugConstraints.DataSource = ds.Tables["Bugs"].Constraints;             BugConstraints.DataBind(  );         }     }       //hand carved       private DataSet CreateDataSet(  )       {          // instantiate a new DataSet object that          // you will fill with tables and relations          DataSet dataSet = new DataSet(  );          // make the bug table and its columns          // mimic the attributes from the SQL database          DataTable tblBugs = new DataTable("Bugs");          DataColumn newColumn; // hold the new columns as you create them          newColumn =            tblBugs.Columns.Add(                "BugID", Type.GetType("System.Int32"));          newColumn.AutoIncrement = true;     // autoincrementing          newColumn.AutoIncrementSeed=1;      // starts at 1          newColumn.AutoIncrementStep=1;      // increments by 1          newColumn.AllowDBNull=false;        // nulls not allowed          // or you can provide a named constraint          UniqueConstraint constraint =             new UniqueConstraint("Unique_BugID",newColumn);          tblBugs.Constraints.Add(constraint);          // create an array of columns for the primary key          DataColumn[] columnArray = new DataColumn[1];          columnArray[0] = newColumn;          // add the array to the Primary key property          tblBugs.PrimaryKey=columnArray;          // The Product column          newColumn = tblBugs.Columns.Add(               "Product", Type.GetType("System.Int32"));          newColumn.AllowDBNull=false;          newColumn.DefaultValue = 1;          // save for foreign key creation          DataColumn bugProductColumn = newColumn;          // The Version column          newColumn = tblBugs.Columns.Add(            "Version", Type.GetType("System.String"));          newColumn.AllowDBNull=false;          newColumn.MaxLength=50;          newColumn.DefaultValue = "0.1";          // The Description column          newColumn = tblBugs.Columns.Add(            "Description", Type.GetType("System.String"));          newColumn.AllowDBNull=false;          newColumn.MaxLength=8000;          newColumn.DefaultValue = "";          // The Reporter column          newColumn = tblBugs.Columns.Add(            "Reporter", Type.GetType("System.Int32"));          newColumn.AllowDBNull=false;          // save for foreign key creation          DataColumn bugReporterColumn = newColumn;          // Add rows based on the db schema you just created          DataRow newRow;      // holds the new row          newRow = tblBugs.NewRow(  );          newRow["Product"] = 1;          newRow["Version"] = "0.1";          newRow["Description"] = "Crashes on load";          newRow["Reporter"] = 5;          tblBugs.Rows.Add(newRow);          newRow = tblBugs.NewRow(  );          newRow["Product"] = 1;          newRow["Version"] = "0.1";          newRow["Description"] =              "Does not report correct owner of bug";          newRow["Reporter"] = 5;          tblBugs.Rows.Add(newRow);          newRow = tblBugs.NewRow(  );          newRow["Product"] = 1;          newRow["Version"] = "0.1";          newRow["Description"] =             "Does not show history of previous action";          newRow["Reporter"] = 6;          tblBugs.Rows.Add(newRow);          newRow = tblBugs.NewRow(  );          newRow["Product"] = 1;          newRow["Version"] = "0.1";          newRow["Description"] =             "Fails to reload properly";          newRow["Reporter"] = 5;          tblBugs.Rows.Add(newRow);          newRow = tblBugs.NewRow(  );          newRow["Product"] = 2;          newRow["Version"] = "0.1";          newRow["Description"] = "Loses data overnight";          newRow["Reporter"] = 5;          tblBugs.Rows.Add(newRow);          newRow = tblBugs.NewRow(  );          newRow["Product"] = 2;          newRow["Version"] = "0.1";          newRow["Description"] = "HTML is not shown properly";          newRow["Reporter"] = 6;          tblBugs.Rows.Add(newRow);          // add the table to the dataset          dataSet.Tables.Add(tblBugs);          // Product Table          // make the Products table and add the columns          DataTable tblProduct = new DataTable("lkProduct");          newColumn = tblProduct.Columns.Add(             "ProductID", Type.GetType("System.Int32"));          newColumn.AutoIncrement = true;     // autoincrementing          newColumn.AutoIncrementSeed=1;      // starts at 1          newColumn.AutoIncrementStep=1;      // increments by 1          newColumn.AllowDBNull=false;        // nulls not allowed          newColumn.Unique=true;              // each value must be unique          newColumn = tblProduct.Columns.Add(             "ProductDescription", Type.GetType("System.String"));          newColumn.AllowDBNull=false;          newColumn.MaxLength=8000;          newColumn.DefaultValue = "";          newRow = tblProduct.NewRow(  );          newRow["ProductDescription"] = "BugX Bug Tracking";          tblProduct.Rows.Add(newRow);          newRow = tblProduct.NewRow(  );          newRow["ProductDescription"] =              "PIM - My Personal Information Manager";          tblProduct.Rows.Add(newRow);          // add the products table to the dataset          dataSet.Tables.Add(tblProduct);          // People          // make the People table and add the columns          DataTable tblPeople = new DataTable("People");          newColumn = tblPeople.Columns.Add(            "PersonID", Type.GetType("System.Int32"));          newColumn.AutoIncrement = true;     // autoincrementing          newColumn.AutoIncrementSeed=1;      // starts at 1          newColumn.AutoIncrementStep=1;      // increments by 1          newColumn.AllowDBNull=false;        // nulls not allowed          UniqueConstraint uniqueConstraint =            new UniqueConstraint(                 "Unique_PersonID",newColumn);          tblPeople.Constraints.Add(uniqueConstraint);          // stash away the PersonID column for the foreign          // key constraint          DataColumn PersonIDColumn = newColumn;          columnArray = new DataColumn[1];          columnArray[0] = newColumn;          tblPeople.PrimaryKey=columnArray;          newColumn = tblPeople.Columns.Add(            "FullName", Type.GetType("System.String"));          newColumn.AllowDBNull=false;          newColumn.MaxLength=8000;          newColumn.DefaultValue = "";          newColumn = tblPeople.Columns.Add(            "eMail", Type.GetType("System.String"));          newColumn.AllowDBNull=false;          newColumn.MaxLength=100;          newColumn.DefaultValue = "";          newColumn = tblPeople.Columns.Add(             "Phone", Type.GetType("System.String"));          newColumn.AllowDBNull=false;          newColumn.MaxLength=20;          newColumn.DefaultValue = "";          newColumn = tblPeople.Columns.Add(             "Role", Type.GetType("System.Int32"));          newColumn.DefaultValue = 0;          newColumn.AllowDBNull=false;          newRow = tblPeople.NewRow(  );          newRow["FullName"] = "Jesse Liberty";          newRow["email"] = "jliberty@libertyassociates.com";          newRow["Phone"] = "617-555-7301";          newRow["Role"] = 1;          tblPeople.Rows.Add(newRow);          newRow = tblPeople.NewRow(  );          newRow["FullName"] = "Dan Hurwitz";          newRow["email"] = "dhurwitz@stersol.com";          newRow["Phone"] = "781-555-3375";          newRow["Role"] = 1;          tblPeople.Rows.Add(newRow);          newRow = tblPeople.NewRow(  );          newRow["FullName"] = "John Galt";          newRow["email"] = "jGalt@franconia.com";          newRow["Phone"] = "617-555-9876";          newRow["Role"] = 1;          tblPeople.Rows.Add(newRow);          newRow = tblPeople.NewRow(  );          newRow["FullName"] = "John Osborn";          newRow["email"] = "jOsborn@oreilly.com";          newRow["Phone"] = "617-555-3232";          newRow["Role"] = 3;          tblPeople.Rows.Add(newRow);          newRow = tblPeople.NewRow(  );          newRow["FullName"] = "Ron Petrusha";          newRow["email"] = "ron@oreilly.com";          newRow["Phone"] = "707-555-0515";          newRow["Role"] = 2;          tblPeople.Rows.Add(newRow);          newRow = tblPeople.NewRow(  );          newRow["FullName"] = "Tatiana Diaz";          newRow["email"] = "tatiana@oreilly.com";          newRow["Phone"] = "617-555-1234";          newRow["Role"] = 2;          tblPeople.Rows.Add(newRow);          // add the People table to the dataset          dataSet.Tables.Add(tblPeople);          // create the Foreign Key constraint          // pass in the parent column from people          // and the child column from Bugs          ForeignKeyConstraint fk =             new ForeignKeyConstraint(                "FK_BugToPeople",PersonIDColumn,bugReporterColumn);          fk.DeleteRule=Rule.Cascade;   // like father like son          fk.UpdateRule=Rule.Cascade;          tblBugs.Constraints.Add(fk);  // add the new constraint          // declare the DataRelation and DataColumn objects          System.Data.DataRelation dataRelation;          System.Data.DataColumn dataColumn1;          System.Data.DataColumn dataColumn2;          // set the dataColumns to create the relationship          // between Bug and BugHistory on the BugID key          dataColumn1 =             dataSet.Tables["People"].Columns["PersonID"];          dataColumn2 =             dataSet.Tables["Bugs"].Columns["Reporter"];          dataRelation =             new System.Data.DataRelation(             "BugsToReporter",             dataColumn1,             dataColumn2);          // add the new DataRelation to the dataset          dataSet.Relations.Add(dataRelation);          return dataSet;       } } 

The Page_Load method calls the CreateDataSet method and binds the first GridView to the Bugs table. Then it binds the second GridView to the constraints collection within the Bugs table (to demonstrate the creation of constraints in the dataset).

 if (!IsPostBack)     {         // call the method that creates the tables and the relations  DataSet ds = CreateDataSet(  );  // set the data source for the grid to the first table         Bugs.DataSource = ds.Tables["Bugs"];         Bugs.DataBind(  );         BugConstraints.DataSource = ds.Tables["Bugs"].Constraints;         BugConstraints.DataBind(  );     } 

The heart of this program is in CreateDataSet , where you have created the dataset.

You begin by instantiating a new (empty) dataset:

 private DataSet CreateDataSet(  )     {        DataSet dataSet = new DataSet(  ); 

Next, you declare a DataTable object, passing in the name of the table as a parameter to the constructor:

 DataTable tblBugs = new DataTable("Bugs"); 

The table you are creating should mimic the data structure of the Bugs table in the SQL Server. Figure 10-9 shows that structure.

To add a column to this DataTable object, you do not call a constructor. Instead you call the Add method of the DataTable object's Columns collection. The Add method takes two parameters, which are the name of the column and its data type:

 DataColumn newColumn;     newColumn =        tblBugs.Columns.Add("BugID", Type.GetType("System.Int32")); 

10.3.2.1. Setting column properties

The Add method creates the new column and returns a reference to it, which you may now manipulate. Since this is to be an identity column (see the highlighted field in Figure 10-9), you'll want to set its AutoIncrement property to true and you'll set the AutoIncrementSeed and AutoIncrementStep properties to set the seed and step values of the identity, respectively. The following code fragment does this:

 newColumn.AutoIncrement = true;     newColumn.AutoIncrementSeed=1;     newColumn.AutoIncrementStep=1; 

Figure 10-9. The structure of the Bugs table in SQL server

The AutoIncrementSeed property sets the initial value for the identity column, and the AutoIncrementStep property sets the increment for each new record. Thus, if the seed were 5 and the step were 3, the first five records would have IDs of 5, 8, 11, 14, and 17. In the case shown, where the seed and step are 1, the first four records have IDs of 1,2,3,4.


10.3.2.2. Setting constraints

Identity columns must not be null, so you'll set the AllowDBNull property of the new column to false :

 newColumn.AllowDBNull=false; 

You can set the Unique property to true to ensure that each entry in this column must be unique:

 newColumn.Unique=true; 

Setting the Unique property to TRue creates an unnamed constraint in the Bugs table's Constraints collection. You can, if you prefer, add a named constraint. To do this, you create an instance of the UniqueConstraint class and pass a name for it into the constructor along with a reference to the column:

 UniqueConstraint constraint =        new UniqueConstraint("Unique_BugID",newColumn); 

You then manually add that constraint to the table's Constraints collection:

 tblBugs.Constraints.Add(constraint); 

If you do add a named constraint, be sure to comment out the Unique property.


This completes the first column in the table. The second column is the Product column, as you can see in Figure 10-10. This column is of type integer, with no nulls and a default value of 1 (see the highlighted property in Figure 10-10). You create the Product column by calling the Add method of the Columns collection of the tblBugs table, this time passing in the type for an integer. Set the AllowDBNull property as you did with the earlier column, and set the DefaultValue property to set the default value for the column. This is illustrated in the following code fragment:

 newColumn = tblBugs.Columns.Add(        "Product", Type.GetType("System.Int32"));     newColumn.AllowDBNull=false;     newColumn.DefaultValue = 1; 

Figure 10-10. The Products column

Looking at Figure 10-10, you can see the third column is Version with a type of varChar .

A varChar is a variable length character string. A varChar can be declared to be any length between 1 and 8000 bytes. Typically you will limit the length of the string as a form of documentation indicating the largest string you expect in the field.


You declare the column type to be string for a varchar , and you can set the length of the string with the MaxLength property, as shown in the following code fragment:

 newColumn = tblBugs.Columns.Add(        "Version", Type.GetType("System.String"));     newColumn.AllowDBNull=false;     newColumn.MaxLength=50;     newColumn.DefaultValue = "0.1"; 

You declare the Description and Reporter columns in a like manner:

 newColumn = tblBugs.Columns.Add("Description", Type.GetType("System.String"));     newColumn.AllowDBNull=false;     newColumn.MaxLength=8000;     newColumn.DefaultValue = "";     newColumn = tblBugs.Columns.Add(        "Reporter", Type.GetType("System.Int32"));     newColumn.AllowDBNull=false; 

10.3.2.3. Adding data to the table

With all the columns declared, you're ready to add rows of data to the table. You do this by calling the DataTable object's NewRow method, which returns an empty DataRow object with the right structure:

 newRow = tblBugs.NewRow(  ); 

You can use the column name as an index into the row's collection of DataColumns , assigning the appropriate value for each column, one by one:

 newRow["Product"] = 1;     newRow["Version"] = "0.1";     newRow["Description"] = "Crashes on load";     newRow["Reporter"] = 5; 

The authors of the DataRows class have implemented the indexer for their class to access the contained Columns collection invisibly . Thus, when you write newRow["Product"] , you access the Product column within the Columns collection of the DataRow object.


When the columns are complete, you add the row to the table's Rows collection by calling the Add method, passing in the row you just created:

 tblBugs.Rows.Add(newRow); 

You are ready to create a new row:

 newRow = tblBugs.NewRow(  );     newRow["Product"] = 1;     newRow["Version"] = "0.1";     newRow["Description"] = "Does not report correct owner of bug";     newRow["Reporter"] = 5;     tblBugs.Rows.Add(newRow); 

When all the rows have been created, you can create an instance of a DataSet object and add the table:

 DataSet dataSet = new DataSet(  );     dataSet.Tables.Add(tblBugs); 

10.3.2.4. Adding additional tables to the DataSet

With the Bugs table added to the new dataset, you can create a new table for lkProduct as illustrated in the database diagram.

 DataTable tblProduct = new DataTable("lkProduct") 

You'll define the columns and add data. Then, you'll add a new table for People . In theory, you could add all the other tables from the previous example, but to keep things simpler, you'll stop with these three.

10.3.2.5. Adding rows with an array of objects

The DataRowCollection object's Add method is overloaded. In the code shown above, you created a new DataRow object, populated its columns, and added the row. You can create an array of Objects , fill the array, and pass the array to the Add method. For example, rather than writing:

 newRow = tblPeople.NewRow(  );     newRow["FullName"] = "Jesse Liberty";     newRow["email"] = "jliberty@libertyassociates.com";     newRow["Phone"] = "617-555-7301";     newRow["Role"] = 1;     tblPeople.Rows.Add(newRow); 

you can create an array of five objects and fill that array with the values you would have added to the columns of the row:

 Object[] PersonArray = new Object[5];     PersonArray[0] = 1;     PersonArray[1] = "Jesse Liberty";     PersonArray[2] = "jliberty@libertyassociates.com";     PersonArray[3] = "617-555-7301";     PersonArray[4] = 1;     tblPeople.Rows.Add(PersonArray); 

In this case, you must manually add a value for the identity column, BugID . When you created the row object, the identity column value was automatically created for you with the right increment from the previous row. Since you are creating an array of objects, you must do this by hand.

Though this technique works, it is generally not desirable. The overloaded version of the Add method that takes a DataRow object is type-safe . Each column must match the definition of the column you've created. With an array of objects, just about anything goes; in .NET, everything derives from Object , and thus, you can pass in any type of data to an array of objects.


10.3.3. Creating Primary Keys

The Bugs table uses the PersonID as a foreign key into the People table. To recreate this, you'll need to create a primary key ( PersonID ) in the People table.

You start by declaring the PersonID column as a unique non-null identity column as you did earlier for the BugID column in Bugs :

 newColumn = tblPeople.Columns.Add("PersonID", Type.GetType("System.Int32"));     newColumn.AutoIncrement = true;     // autoincrementing     newColumn.AutoIncrementSeed=1;      // starts at 1     newColumn.AutoIncrementStep=1;      // increments by 1     newColumn.AllowDBNull=false;        // nulls not allowed     // add the unique constraint     UniqueConstraint uniqueConstraint =       new UniqueConstraint("Unique_PersonID",newColumn);     tblPeople.Constraints.Add(uniqueConstraint); 

To create the primary key, you must set the PrimaryKey property of the table. This property takes an array of DataColumn objects.

In many tables, the primary key is not a single column but rather two or more columns. For example, you might keep track of orders for a customer. A given order might be order number 17. Your database may have many orders whose order number is 17. What uniquely identifies a given order is the order number combined with the customer number. Thus, that table would use a compound key of the order number and the customer number.


The primary key for the People table is a single column: PersonID . To set the primary key, you create an array (in this case, with one member) and assign to that member the column(s) you want to make the primary key:

 columnArray = new DataColumn[1];     columnArray[0] = newColumn; 

The newColumn object contains a reference to the PersonID column returned from calling Add . You assign the array to the PrimaryKey property of the table:

 tblPeople.PrimaryKey=columnArray; 

10.3.4. Creating Foreign Keys

The PersonID acts as a primary key in People and as a foreign key in Bugs . To create the foreign key relationship, you'll instantiate a new object of type ForeignKeyCon-straint , passing in the name of the constraint ( FK_BugToPeople ) and a reference to the two columns.

To facilitate passing references from the key fields to the ForeignKeyConstraint constructor, you'll want to squirrel away a reference to the PersonID column in People and the Reporter column in Bugs . After you create the columns, save a reference:

 newColumn =        tblBugs.Columns.Add("Reporter", Type.GetType("System.Int32"));     newColumn.AllowDBNull=false;  DataColumn bugReporterColumn =          newColumn; // save for foreign key creation  

Assuming you've saved the Reporter column in bugReporterColumn and the PersonID column from People in PersonIDColumn , you can create the ForeignKeyConstraint object:

 ForeignKeyConstraint fk =       New ForeignKeyConstraint(             "FK_BugToPeople",PersonIDColumn,bugReporterColumn); 

This creates the Foreign Key Constraint named fk . Before you add it to the Bugs table, you must set two properties:

 fk.DeleteRule=Rule.Cascade;     fk.UpdateRule=Rule.Cascade; 

The DeleteRule determines the action that will occur when a row is deleted from the parent table. Similarly, the UpdateRule determines what will happen when a row is updated in the parent column. The potential values are enumerated by the Rule enumeration, as shown in Table 10-9.

Table 10-9. Rule enumeration

Member name

Description

Cascade

Delete or update related rows (this is the default).

None

Take no action on related rows.

SetDefault

Set the values in the related rows to the value contained in the DefaultValue property.

SetNull

Set the related rows to null.


In this case, the values are set to Rule.Cascade ; if a record is deleted or updated from the parent table, all the child records will be deleted or updated as well. You can now add the foreign key constraint to the Bugs table:

 tblBugs.Constraints.Add(fk); 

10.3.5. Creating Data Relations

As you saw earlier in the chapter, you can encapsulate the relationship between tables in a DataRelation object. The code for building relationships among hand-crafted DataTables is like the code you saw earlier when you pulled the data structure from the database:

 System.Data.DataRelation dataRelation;     System.Data.DataColumn dataColumn1;     System.Data.DataColumn dataColumn2;     // set the dataColumns to create the relationship     // between Bug and BugHistory on the BugID key     dataColumn1 =        dataSet.Tables["People"].Columns["PersonID"];     dataColumn2 =        dataSet.Tables["Bugs"].Columns["Reporter"];     dataRelation =        new System.Data.DataRelation(        "BugsToReporter",        dataColumn1,        dataColumn2);     // add the new DataRelation to the dat     dataSet.Relations.Add(dataRelation); 

The output is shown in Figure 10-11.

Figure 10-11. Bug Tracker



Programming ASP. NET
Programming ASP.NET 3.5
ISBN: 0596529562
EAN: 2147483647
Year: 2003
Pages: 173

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net