Microsoft ADO .NET 4 Step by Step - p 11 ppt

10 295 0
Microsoft ADO .NET 4 Step by Step - p 11 ppt

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

Thông tin tài liệu

76 Microsoft ADO.NET 4 Step by Step Establishing Relationships Between Tables Before focusing on the relationship features of the DataSet class, it is essential to have a clear understanding of what it means for two tables to be related. Understanding Table Relations In relational database modeling, the term cardinality describes the type of relationship that two tables have. There are three main types of database model cardinality:  One-to-One A record in one table matches exactly one record in another table. This is commonly used to break a table with a large number of columns into two distinct tables for processing convenience. Table1 Record 1 Record 2 Record 3 Table2 Record 1 Record 2 Record 3  One-to-Many One record in a “parent” table has zero or more “child” records in another table. A typical use for the one-to-many relationship is in an ordering system in which a single customer record (the parent) will have none, one, or many order re- cords (the children) on file. Likewise, a single order record will have multiple order line items. One-to-many relationships are the most common type of table link in relational databases. Customer Customer 1 Customer 2 Customer 3 Order Order 1 for Customer 1 Order 2 for Customer 1 Order 1 for Customer 2  Many-to-Many In this third and most complex type of link, one record in the first table is associated with zero or more records in the second table, and each record in the second table can also be associated with zero or more records in the first table. Students taking classes is a typical real-world example of a many-to-many relationship. Each student can take multiple classes, and each class can have multiple students listed as class participants. Chapter 5 Bringing Related Data Together 77 Student Student 1 Student 2 Student 3 Class Class 1 Class 2 Class 3 Fortunately, all three of these model relationships share a common physical implementation concept: the foreign key—the use of a table’s identifying column(s) by another table. In a foreign-key relationship, both tables include a column (or multiple columns when the master table uses a multipart key) that uses an agreed-upon domain of values. When records in each table share a common value for that column, the records are related. For example, in a customer-order relationship, the Customer table includes a customer iden- tification column that uniquely defines each record. The associated Order table also includes a customer identification column. Each order that shares a customer identifier with a specific customer record belongs to that customer record. There might be multiple order records that include that customer’s identifier, each of which is related to the same customer. Note The name given to the identifying column in the first table doesn’t need to be the same as the name of the column in the second table. Only the data relationships are important, not the names given to the columns in those relationships. Records in a one-to-one relationship work the same way, but there is never more than one occurrence of a specific identifier value in each table. If a record in one table always has a match in the second table, it doesn’t matter which one is the parent and which is the child. If one table’s records are optional, the table with the optional records is the child. Many-to-many relationships also use the foreign-key concept, but they require a “go-between” table that indicates which two keys link up. Both primary tables are the parent; the interim table is the child. Student Student 1 Student 2 Student 3 StudentClassInterim Student 1 Student 1 Student 1 Class 1 Class 2 Class 3 Student 3 Class 2 Student 3 Class 3 Class Class 1 Class 2 Class 3 78 Microsoft ADO.NET 4 Step by Step There are some expectations that come with these types of data relationships:  The relationship column in the parent or master table must contain unique values; no duplicates are allowed. Also, NULL values are not allowed in this column.  Any value that appears in the relationship column of the child must have a related par- ent record. If the child record has no related parent record, that child record must be deleted or its link-column value must be set to NULL. In short, every parent must be unique, and every child requires a parent. Creating Data Relations The D ataRelation class, found within the System.Data namespace, makes table joins within a DataSet possible. Each relationship includes a parent and a child. The DataRelation class even uses the terms “parent” and “child” in its defining members. To create a relationship between two DataSet tables, first add the parent and child table to the data set. Then create a new DataRelation instance, passing its constructor the name of the new relationship, plus a reference to the linking columns in each table. The following code joins a Customer table with an Order table, linking the Customer.ID column as the par- ent with the related Order.CustomerID column as the child: C# DataSet orderTracking = new DataSet("OrderTracking"); orderTracking.Tables.Add(customerTable); orderTracking.Tables.Add(orderTable); DataRelation customerOrder = new DataRelation("CustomerOrder", customerTable.Columns["ID"], orderTable.Columns["CustomerID"]); orderTracking.Relations.Add(customerOrder); Visual Basic Dim orderTracking As New DataSet("OrderTracking") orderTracking.Tables.Add(customerTable) orderTracking.Tables.Add(orderTable) Dim customerOrder As New DataRelation("CustomerOrder", customerTable.Columns!ID, orderTable.Columns!CustomerID) orderTracking.Relations.Add(customerOrder) For tables with multipart relational keys, the second and third arguments to the DataRelation constructor each accept an array of DataColumn objects. Note Columns bound in a relationship must always be the same data type. In tables with multi- part keys, each positional part between the tables must be the same data type. Chapter 5 Bringing Related Data Together 79 Adding a Relationship Between Two Tables: C# Note This exercise uses the “Chapter 5 CSharp” sample project and continues the previous exercise in this chapter. 1. Open the source code view for the FlightInfo form. Locate the BuildSampleDataSet function. 2. Just after the “Build the relationship between the tables” comment, add the following statements: tableLink = new DataRelation("FlightLeg", parentTable.Columns["ID"], childTable.Columns["FlightID"], true); result.Relations.Add(tableLink); These lines create a new DataRelation instance named “FlightLeg” using the matching DataColumn instances from the two tables. Adding the DataRelatio n to the DataSet completes the column-linking process. Adding a Relationship Between Two Tables: Visual Basic Note This exercise uses the “Chapter 5 VB” sample project and continues the previous exercise in this chapter. 1. Open the source code view for the FlightInfo form. Locate the BuildSampleDataSet function. 2. Just after the “Build the relationship between the tables” comment, add the following statements: tableLink = New DataRelation("FlightLeg", parentTable.Columns("ID"), childTable.Columns("FlightID"), True) result.Relations.Add(tableLink) These lines create a new DataRelation instance named “FlightLeg” using the matching DataColumn instances from the two tables. Adding the DataRelatio n to the DataSet completes the column-linking process. Locating Parent and Child Records After you’ve established a parent-child relationship between two tables, it’s easy to re- trieve data that capitalizes on that relationship. The DataRow class includes two methods— GetChildRows and GetParentRow—that retrieve the relevant row(s) at the other end of a linked relationship. Because a column could be involved in multiple relationships, you must 80 Microsoft ADO.NET 4 Step by Step pass either the name or the instance of the relationship to the relevant method. The follow- ing statements retrieve the customer (parent) record given an order (child) record row, de- pending on the DataRelation with a name of “CustomerOrder”: C# DataRow customer = whichOrder.GetParentRow("CustomerOrder"); Visual Basic Dim customer As DataRow = whichOrder.GetParentRow("CustomerOrder") Getting the child records for a parent row uses nearly identical code. Because a parent can have multiple children, the GetChildRows method returns an array of DataRow matches. C# DataRow[] orders = whichCustomer.GetChildRows("CustomerOrder"); Visual Basic Dim orders() As DataRow = whichCustomer.GetChildRows("CustomerOrder") The D ataRow class also includes a variant of G etParentRow (named GetParentRows) that returns multiple parent rows for a single child record. This is useful for parent-child relation- ships that are linked on columns other than the parent’s primary key. In the class-student example mentioned previously, consider a university that has multiple campuses within a city. If both students and classes are associated with a specific campus, a link can be established between the columns in each table that define the campus. C# DataTable classTable = new DataTable("Class"); // Add columns, including classTable.Columns.Add("Campus", typeof(string)); DataTable studentTable = new DataTable("Student"); // Add columns, including studentTable.Columns.Add("Campus", typeof(string)); DataSet siteCourses = new DataSet("SiteCourses"); siteCourses.Tables.Add(classTable); siteCourses.Tables.Add(studentTable); DataRelation classStudent = new DataRelation("ClassStudent", classTable.Columns["Campus"], studentTable.Columns["Campus"], false); siteCourses.Relations.Add(classStudent); // Later, get available classes for a student by campus. DataRow[] availableClasses = whichStudent.GetParentRows("ClassStudent"); Chapter 5 Bringing Related Data Together 81 Visual Basic Dim classTable As New DataTable("Class") ' Add columns, including classTable.Columns.Add("Campus", GetType(String)) Dim studentTable As New DataTable("Student") ' Add columns, including studentTable.Columns.Add("Campus", GetType(String)) Dim siteCourses As New DataSet("SiteCourses") siteCourses.Tables.Add(classTable) siteCourses.Tables.Add(studentTable) Dim classStudent As New DataRelation("ClassStudent", classTable.Columns("Campus"), studentTable.Columns("Campus"), False) siteCourses.Relations.Add(classStudent) ' Later, get available classes for a student by campus. Dim availableClasses() As DataRow = whichStudent.GetParentRows("ClassStudent") Because the parent table can include duplicate values in its related column, this relationship doesn’t follow the normal rules for a key-based, one-to-many relationship. It is instead a form of many-to-many cardinality, albeit one that does not involve either table’s primary key. Normally, new DataRelation instances create special “constraint” objects that establish the re- lationship rules, such as the need for a unique primary key. (This next section, "Defining Table Constraints,” discusses these constraints.) In this many-to-many relationship, such constraints would generate errors. Therefore, when creating the DataRelation instance, the code passed a fourth Boolean argument with a value of False to the constructor, telling it to dispense with the constraints. Defining Table Constraints As mentioned earlier in this chapter, data relationships come with certain expectations known as constraints, expressed through the System.Data.Constraint class. ADO.NET supports two types of constraints, both designed to maintain the integrity of each table’s data: unique column (System.Data.UniqueConstraint) and foreign key (System.Data.ForeignKeyConstraint). As you would expect, the unique column constraint prevents duplicate values from showing up in a table column, a requirement for the parent column in a one-to-many relationship. Attempts to add a duplicate value to a unique column will result in a thrown exception. The foreign-key constraint establishes similar limitations on the participating columns. Although the parent column might include values that do not appear in the child table’s joined column, the reverse is not true. In a one-to-many relationship, any value in the child column must exist in the parent column as well. The ForeignKeyConstraint class enforces this 82 Microsoft ADO.NET 4 Step by Step rule. But unlike the UniqueConstraint class, which just throws an exception when you violate the rule, ForeignKeyConstraint gives you options for how ADO.NET should behave when data violates the foreign-key regulation. There are four rules that can be followed when a parent- column value is updated or deleted:  The child rows can be automatically updated or deleted in the same manner.  The child column values can be set to NULL.  The child column values can be set to a default value, assuming that the value does not violate the foreign-key constraint.  An exception can be thrown. This is the default. You define these actions by setting the DeleteRule and UpdateRule properties in the ForeignKeyConstraint object as needed. Each field can be set to one of the following enumer- ated values:  System.Data.Rule.Cascade  System.Data.Rule.SetNull  System.Data.Rule.SetDefault  System.Data.Rule.None By default, adding a DataRelation that links two tables in a DataSet adds both a unique constraint to the parent column and a foreign-key constraint to the child column. As shown previously, you can also pass an argument to the DataRelation constructor that prevents the creation of these constraints and add the constraints yourself as needed. Note If you choose to define the constraints for a relationship yourself, you must (1) add a UniqueConstraint to the parent column; (2) add a ForeignKeyConstraint to the child column; (3) update the appropriate properties in the DataRelation instance, including the ChildKeyConstraint and the ParentKeyConstraint properties; and (4) make various changes to properties in the Constraint, DataTable, and DataRelation instances so that they all reference each other. To ensure proper configuration between the fields, it is often best to let the DataRelation constructor fill in all these fields on your behalf. To add a constraint manually, create and fill out an instance of either UniqueConstraint or ForeignKeyConstraint; you can’t create an instance of the Constraint class directly. Then add the new instance to the DataTable object’s Constraints collection. Chapter 5 Bringing Related Data Together 83 C# Constraint exemptUnique = new UniqueConstraint( customers.Columns["TaxExemptID"]); customers.Constraints.Add(exemptUnique); Visual Basic Dim exemptUnique As Constraint = New UniqueConstraint( customers.Columns!TaxExemptID) customers.Constraints.Add(exemptUnique) The second Boolean argument in the UniqueConstraint constructor can be set to True to indicate primary key columns. Other constructor variations let you name the constraint or associate it with multiple columns. Implementing a many-to-many relationship based on primary keys—the multiple-students- in-multiple-classes scenario diagrammed earlier in this chapter—requires an interim table to join the two main tables. The interim table will have a two-part primary key, with each part hosting the primary key of one of the two main joined tables. Adding a multipart UniqueConstra int instance to the interim table prevents a pair of records between the tables from being joined twice to each other. C# DataTable studentTable = new DataTable("Student"); // Add columns, including studentTable.Columns.Add("ID", typeof(long)); DataTable classTable = new DataTable("Class"); // Add columns, including classTable.Columns.Add("ID", typeof(long)); DataTable interimTable = new DataTable("StudentClassInterim"); // Add columns, including interimTable.Columns.Add("StudentID", typeof(long)); interimTable.Columns.Add("ClassID", typeof(long)); // Make the linking fields unique. Constraint interimKey = new UniqueConstraint( new DataColumn[] { interimTable.Columns["StudentID"], interimTable.Columns["ClassID"] }, true); interimTable.Constraints.Add(interimKey); 84 Microsoft ADO.NET 4 Step by Step // Relations exist within a data set context. DataSet registration = new DataSet("Registration"); registration.Tables.Add(classTable); registration.Tables.Add(studentTable); registration.Tables.Add(interimTable); // Add standard joins between the core tables and the interim. DataRelation joinPart = new DataRelation("ClassToStudent", classTable.Columns["ID"], interimTable.Columns["ClassID"], true); registration.Relations.Add(joinPart); joinPart = new DataRelation("StudentToClass", studentTable.Columns["ID"], interimTable.Columns["StudentID"], true); registration.Relations.Add(joinPart); Visual Basic Dim studentTable As New DataTable("Student") ' Add columns, including studentTable.Columns.Add("ID", GetType(Long)) Dim classTable As New DataTable("Class") ' Add columns, including classTable.Columns.Add("ID", GetType(Long)) Dim interimTable As New DataTable("StudentClassInterim") ' Add columns, including interimTable.Columns.Add("StudentID", GetType(Long)) interimTable.Columns.Add("ClassID", GetType(Long)) ' Make the linking fields unique. Dim interimKey As Constraint = New UniqueConstraint( { interimTable.Columns!StudentID, interimTable.Columns!ClassID }, True) interimTable.Constraints.Add(interimKey) ' Relations exist within a data set context. Dim registration As New DataSet("Registration") registration.Tables.Add(classTable) registration.Tables.Add(studentTable) registration.Tables.Add(interimTable) ' Add standard joins between the core tables and the interim. Dim joinPart As New DataRelation("ClassToStudent", classTable.Columns("ID"), interimTable.Columns("ClassID"), True) registration.Relations.Add(joinPart) joinPart = New DataRelation("StudentToClass", studentTable.Columns("ID"), interimTable.Columns("StudentID"), True) registration.Relations.Add(joinPart) Chapter 5 Bringing Related Data Together 85 Defining the Update and Delete Rules in a DataRelation : C# Note This exercise uses the “Chapter 5 CSharp” sample project and continues the previous exer- cise in this chapter. 1. Open the source code view for the FlightInfo form. Locate the RefreshConstraints method. The application lets the user alter the rules for adjusting the child table when changes are made to the parent table. The RefreshConstraints routine updates the relevant constraint with the user’s rule choice. 2. Just after the “Alter its cascade rules” comment, add the following statements: linkConstraint.DeleteRule = (System.Data.Rule)DeleteRule.SelectedItem; linkConstraint.UpdateRule = (System.Data.Rule)UpdateRule.SelectedItem; 3. Run the program. The Update Rule and Delete Rule fields are both set to None by default. This prevents parent records (Flights) from being deleted or having their ID col- umn values changed if related child rows (Legs) exist. 4. Test cascade updates. Set the Update Rule field to Cascade. Select the first row in the Flights field, the one with ID 834. Click the (Flights) Edit button. Use the Edit Flight form that appears to alter the Flight ID value from 834 to another value, such as 759. Click OK on that editor form. 5. Review the Flights and Legs fields. Not only did the first row in the Flights field have its ID value changed to 759 but the FlightID values for the related rows in the Legs field changed to 759 as well. . 3 Class Class 1 Class 2 Class 3 78 Microsoft ADO. NET 4 Step by Step There are some expectations that come with these types of data relationships:  The relationship column in the parent or master table. involved in multiple relationships, you must 80 Microsoft ADO. NET 4 Step by Step pass either the name or the instance of the relationship to the relevant method. The follow- ing statements retrieve. In a one-to-many relationship, any value in the child column must exist in the parent column as well. The ForeignKeyConstraint class enforces this 82 Microsoft ADO. NET 4 Step by Step rule.

Ngày đăng: 05/07/2014, 19:20

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

Tài liệu liên quan