Tài liệu Updating a DataSet with a Many-to-Many Relationship ppt

19 304 0
Tài liệu Updating a DataSet with a Many-to-Many Relationship ppt

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

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

Thông tin tài liệu

[ Team LiB ] Recipe 4.10 Updating a DataSet with a Many-to-Many Relationship Problem You have a DataSet that contains two tables that have a many-to-many relationship between them using a third junction table. You get referential integrity errors when you try to update changes to the data in this DataSet back to the data source. You need to do this successfully. Solution Use the techniques described in the discussion. The schema of table TBL0410Parent used in this solution is shown in Table 4-5 . Table 4-5. TBL0410Parent schema Column name Data type Length Allow nulls? ParentId int 4 No Field1 nvarchar 50 Yes Field2 nvarchar 50 Yes The schema of table TBL0410Child used in this solution is shown in Table 4-6. Table 4-6. TBL0410Child schema Column name Data type Length Allow nulls? ChildId int 4 No Field3 nvarchar 50 Yes Field4 nvarchar 50 Yes The schema of table TBL0410ParentChild used in this solution is shown in Table 4-7. Table 4-7. TBL0410ParentChild schema Column name Data type Length Allow nulls? ParentId int 4 No ChildId int 4 No The solution uses eleven stored procedures described in Table 4-8. Table 4-8. Stored procedures for solution in Recipe 4.10 Name Description SP0410_DeleteChild Deletes the Child record specified by the ChildId input parameter. SP0410_DeleteParent Deletes the Parent record specified by the ParentId input parameter. SP0410_DeleteParentChild Deletes the ParentChild record specified by the ParentId and ChildId input parameters. SP0410_GetChild Gets the Child record corresponding to the ChildId specified or returns all Child records if no ChildId is specified. SP0410_GetParent Gets the Parent record corresponding to the ParentId specified or returns all Parent records if no ParentId is specified. SP0410_GetParentChild Gets the ParentChild records corresponding to the ParentId specified or returns all ParentChild records if no ParentId is specified. SP0410_InsertChild Adds a new Child record. The stored procedure returns the ChildId value generated by the data source as both an output parameter and in the first returned record. SP0410_InsertParent Adds a new Parent record. The stored procedure returns the ParentId value generated by the data source as both an output parameter and in the first returned record. SP0410_InsertParentChild Adds a new ParentChild record. SP0410_UpdateChild Updates the Child record matching the specified ChildId. SP0410_UpdateParent Updates the Parent record matching the specified ParentId. The sample code contains five event handlers and four methods: Form.Load This event handler sets up the sample by creating a DataSet containing a parent, child, and many-to-many junction table, as well as the DataRelation objects between them. A DataAdapter object is created for each table and the stored procedures to select, delete, insert, and update records in the data source are specified for each. The LoadData( ) method is called to retrieve data for each table in the DataSet. Finally, the default view for the parent and the child tables are bound to data grids on the form. LoadData( ) This method calls the Fill( ) method of the DataAdapter for each of the parent, child, and junction tables. CreateData( ) This method creates random data in both the parent and child tables and randomly creates relationships between them by adding records to the junction table. UpdateData( ) This method updates all changes in the DataSet back to the data source by calling in the correct order the Update( ) method of the DataAdapter object for subsets of the data in each of the parent, child, and junction tables. Create Button.Click This event handler calls the CreateData( ) method to add random data to the DataSet. Modify Button.Click This event handler makes random changes to the data in the DataSet: • Rows from the parent and child table are deleted or have values in their fields modified. • Parent/child relationships are eliminated by deleting records from the junction table. • The CreateData( ) method is called to create new data. • The UpdateData( ) method is called to update all of the changes made to the DataSet with the data source. Delete Button.Click This event handler deletes all data from the parent, child, and junction table. The UpdateData( ) method is called to update the changes made to the DataSet with the data source. Refresh Button.Click This event handler clears all data from the DataSet. LoadData( ) is then called to load all data from the data source into the parent, child, and junction tables in the DataSet. The 11 stored procedures used in this example are shown in Example 4-13 through Example 4-23 . Example 4-13. Stored procedure: SP0410_DeleteChild CREATE PROCEDURE SP0410_DeleteChild @ChildId int AS SET NOCOUNT ON delete from TBL0410Child where ChildId=@ChildId return 0 Example 4-14. Stored procedure: SP0410_DeleteParent CREATE PROCEDURE SP0410_DeleteParent @ParentId int AS SET NOCOUNT ON delete from TBL0410Parent where ParentId=@ParentId return 0 Example 4-15. Stored procedure: SP0410_DeleteParentChild CREATE PROCEDURE SP0410_DeleteParentChild @ParentId int, @ChildId int AS SET NOCOUNT ON delete from TBL0410ParentChild where ParentId=@ParentId and ChildId=@ChildId return 0 Example 4-16. Stored procedure: SP0410_GetChild CREATE PROCEDURE SP0410_GetChild @ChildId int=null AS SET NOCOUNT ON if @ChildId is not null begin select ChildID, Field3, Field4 from TBL0410Child where ChildId=@ChildId return 0 end select ChildId, Field3, Field4 from TBL0410Child return 0 Example 4-17. Stored procedure: SP0410_GetParent CREATE PROCEDURE SP0410_GetParent @ParentId int=null AS SET NOCOUNT ON if @ParentId is not null begin select ParentId, Field1, Field2 from TBL0410Parent where ParentId=@ParentId return 0 end select ParentId, Field1, Field2 from TBL0410Parent return 0 Example 4-18. Stored procedure: SP0410_GetParentChild CREATE PROCEDURE SP0410_GetParentChild @ParentId int=null AS if @ParentId is not null begin select ParentId, ChildID from TBL0410ParentChild where ParentId=@ParentId return 0 end select ParentId, ChildID from TBL0410ParentChild return 0 Example 4-19. Stored procedure: SP0410_InsertChild CREATE PROCEDURE SP0410_InsertChild @ChildId int output, @Field3 nvarchar(50)=null, @Field4 nvarchar(50)=null AS SET NOCOUNT ON insert TBL0410Child( Field3, Field4) values ( @Field3, @Field4) if @@rowcount=0 return 1 set @ChildId=Scope_Identity( ) select @ChildId ChildId return 0 Example 4-20. Stored procedure: SP0410_InsertParent CREATE PROCEDURE SP0410_InsertParent @ParentId int output, @Field1 nvarchar(50)=null, @Field2 nvarchar(50)=null AS SET NOCOUNT ON insert TBL0410Parent( Field1, Field2) values ( @Field1, @Field2) if @@rowcount=0 return 1 set @ParentId=Scope_Identity( ) select @ParentId ParentId return 0 Example 4-21. Stored procedure: SP0410_InsertParentChild CREATE PROCEDURE SP0410_InsertParentChild @ParentId int, @ChildId int AS SET NOCOUNT ON insert TBL0410ParentChild( ParentId, ChildId) values ( @ParentId, @ChildId) if @@rowcount=0 return 1 return 0 Example 4-22. Stored procedure: SP0410_UpdateChild CREATE PROCEDURE SP0410_UpdateChild @ChildId int, @Field3 nvarchar(50)=null, @Field4 nvarchar(50)=null AS SET NOCOUNT ON update TBL0410Child set Field3=@Field3, Field4=@Field4 where ChildId=@ChildId if @@rowcount=0 return 1 return 0 Example 4-23. Stored procedure: SP0410_UpdateParent CREATE PROCEDURE SP0410_UpdateParent @ParentId int, @Field1 nvarchar(50)=null, @Field2 nvarchar(50)=null AS SET NOCOUNT ON update TBL0410Parent set Field1=@Field1, Field2=@Field2 where ParentId=@ParentId if @@rowcount=0 return 1 return 0 The C# code for updating a DataSet with a many-to-one relationship is shown in Example 4-24. Example 4-24. File: UpdateManyToManyRelationshipForm.cs // Namespaces, variables, and constants using System; using System.Configuration; using System.Windows.Forms; using System.Data; using System.Data.SqlClient; private DataSet ds; private SqlDataAdapter daParent, daParentChild, daChild; private const String PARENTTABLENAME = "TBL0410Parent"; private const String PARENTCHILDTABLENAME = "TBL0410ParentChild"; private const String CHILDTABLENAME = "TBL0410Child"; // Table column name constants for Parent table private const String PARENTID_FIELD = "ParentId"; private const String FIELD1_FIELD = "Field1"; private const String FIELD2_FIELD = "Field2"; // Table column parameter name constants for Child table private const String CHILDID_FIELD = "ChildId"; private const String FIELD3_FIELD = "Field3"; private const String FIELD4_FIELD = "Field4"; // Stored procedure name constants private const String DELETEPARENT_SP = "SP0410_DeleteParent"; private const String GETPARENT_SP = "SP0410_GetParent"; private const String INSERTPARENT_SP = "SP0410_InsertParent"; private const String UPDATEPARENT_SP = "SP0410_UpdateParent"; private const String DELETEPARENTCHILD_SP = "SP0410_DeleteParentChild"; private const String GETPARENTCHILD_SP = "SP0410_GetParentChild"; private const String INSERTPARENTCHILD_SP = "SP0410_InsertParentChild"; private const String DELETECHILD_SP = "SP0410_DeleteChild"; private const String GETCHILD_SP = "SP0410_GetChild"; private const String INSERTCHILD_SP = "SP0410_InsertChild"; private const String UPDATECHILD_SP = "SP0410_UpdateChild"; [...]... insertCommand.Parameters.Add(CHILDID_PARM, SqlDbType.Int, 0, CHILDID_FIELD); daParentChild.InsertCommand = insertCommand; LoadData( ); dataGridParent.DataSource = parentTable.DefaultView; dataGridChild.DataSource = childTable.DefaultView; } private void LoadData( ) { // Fill the dataset daParent.Fill(ds, PARENTTABLENAME); daChild.Fill(ds, CHILDTABLENAME); daParentChild.Fill(ds, PARENTCHILDTABLENAME); } private... } private void UpdateData( ) { try { daParentChild.Update(ds.Tables[PARENTCHILDTABLENAME].Select( null, null, DataViewRowState.Deleted)); daChild.Update(ds.Tables[CHILDTABLENAME].Select( null, null, DataViewRowState.Deleted)); daParent.Update(ds.Tables[PARENTTABLENAME].Select( null, null, DataViewRowState.Deleted)); daParent.Update(ds.Tables[PARENTTABLENAME].Select( null, null, DataViewRowState.ModifiedCurrent));... daParent.Update(ds.Tables[PARENTTABLENAME].Select( null, null, DataViewRowState.Added)); daChild.Update(ds.Tables[CHILDTABLENAME].Select( null, null, DataViewRowState.ModifiedCurrent)); daChild.Update(ds.Tables[CHILDTABLENAME].Select( null, null, DataViewRowState.Added)); daParentChild.Update(ds.Tables[PARENTCHILDTABLENAME].Select( null, null, DataViewRowState.Added)); } catch (Exception ex) { MessageBox.Show(ex.Message);... daChild.SelectCommand.Connection); updateCommand.CommandType = CommandType.StoredProcedure; updateCommand.Parameters.Add(CHILDID_PARM, SqlDbType.Int, 0, CHILDID_FIELD); updateCommand.Parameters.Add(FIELD3_PARM, SqlDbType.NVarChar, 50, FIELD3_FIELD); updateCommand.Parameters.Add(FIELD4_PARM, SqlDbType.NVarChar, 50, FIELD4_FIELD); daChild.UpdateCommand = updateCommand; // Create the ParentChild DataAdapter daParentChild... ds.Tables.Add(parentTable); ds.Tables.Add(parentChildTable); ds.Tables.Add(childTable); ds.Relations.Add(new DataRelation("Parent_ParentChild", parentTable.Columns[PARENTID_FIELD], parentChildTable.Columns[PARENTID_FIELD], true)); ds.Relations.Add(new DataRelation("Child_ParentChild", childTable.Columns[CHILDID_FIELD], parentChildTable.Columns[CHILDID_FIELD], true)); // Create the Parent DataAdapter daParent... insertCommand.Parameters.Add(FIELD2_PARM, SqlDbType.NVarChar, 50, FIELD2_FIELD); daParent.InsertCommand = insertCommand; // Build the parent update command SqlCommand updateCommand = new SqlCommand(UPDATEPARENT_SP, daParent.SelectCommand.Connection); updateCommand.CommandType = CommandType.StoredProcedure; updateCommand.Parameters.Add(PARENTID_PARM, SqlDbType.Int, 0, PARENTID_FIELD); updateCommand.Parameters.Add(FIELD1_PARM,... part of the concurrency handling process, the UpdateCommand property of child tables must accept either its Original or the Current value If the primary key is an AutoIncrement value and its value is generated by the database, the InsertCommand must return the primary key value from the data source and use it to update the value in the DataSet The DataSet will then automatically cascade this new value... sender, System.EventArgs e) { ds.Clear( ); LoadData( ); } Discussion To avoid referential integrity problems when updating a data source with changes in a DataSet having tables related with a many-to-many relationship, update the rows in the following order: 1 2 3 4 5 6 7 8 Deleted junction rows Deleted child rows Deleted parent rows Updated parent rows Inserted parent rows Updated child rows Inserted... same statement Pass a bitwise combination into the select method as shown here: daParent.Update(ds.Tables[PARENTTABLENAME].Select(null, null, DataViewRowState.Added | DataViewRowState.ModifiedCurrent)); If the primary key can be modified, the database must cascade the updated primary key values to the child records; otherwise, a referential integrity violation will occur If the foreign key is used as... PARENTID_FIELD); updateCommand.Parameters.Add(FIELD1_PARM, SqlDbType.NVarChar, 50, FIELD1_FIELD); updateCommand.Parameters.Add(FIELD2_PARM, SqlDbType.NVarChar, 50, FIELD2_FIELD); daParent.UpdateCommand = updateCommand; // Create the Child DataAdapter daChild = new SqlDataAdapter(GETCHILD_SP, ConfigurationSettings.AppSettings["Sql_ConnectString"]); daChild.SelectCommand.CommandType = CommandType.StoredProcedure; // . [ Team LiB ] Recipe 4.10 Updating a DataSet with a Many-to-Many Relationship Problem You have a DataSet that contains two tables that have a many-to-many. sample by creating a DataSet containing a parent, child, and many-to-many junction table, as well as the DataRelation objects between them. A DataAdapter

Ngày đăng: 26/01/2014, 10:20

Từ khóa liên quan

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

Tài liệu liên quan