Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 22 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
22
Dung lượng
54,33 KB
Nội dung
[ Team LiB ]
Recipe 6.6 AvoidingReferentialIntegrity Problems When Updating the Data
Source
Problem
You sometimes get referentialintegrity errors when you update a DataSet that contains
related parent, child, and grandchild records back to the underlying data source, but want
to perform the update without errors.
Solution
Use one DataAdapter for each DataTable to update the deleted, updated, and inserted
rows as shown in the following example.
The schema of table TBL0606Parent used in this solution is shown in Table 6-2
.
Table 6-2. TBL0606Parent schema
Column name Data type Length Allow nulls?
ParentId int 4 No
Field1 nvarchar 50 Yes
Field2 nvarchar 50 Yes
The schema of table TBL00606Child used in this solution is shown in Table 6-3.
Table 6-3. TBL0606Child schema
Column name Data type Length Allow nulls?
ChildId int 4 No
ParentId int 4 No
Field3 nvarchar 50 Yes
Field4 nvarchar 50 Yes
The schema of table TBL0606Grandchild used in this solution is shown in Table 6-4.
Table 6-4. TBL0606Grandchild schema
Column name Data type Length Allow nulls?
GrandchildId int 4 No
ChildId int 4 No
Field5 nvarchar 50 Yes
Field6 nvarchar 50 Yes
The sample uses 12 stored procedures:
SP0606_GetParent
Used to retrieve a single record from the Parent table if the optional @ParentId
parameter is specified or all Parent records if it is not
SP0606_DeleteParent
Used to delete the record specified by the @ParentId parameter from the Parent
table
SP0606_InsertParent
Used to insert a record into the Parent table and return the ParentId identity value
for the new record
SP0606_UpdateParent
Used to update all field values for the record in the Parent table specified by the
@ParentId input parameter
SP0606_GetChild
Used to retrieve a single record from the Child table if the optional @ChildId
parameter is specified or all Child records if it is not
SP0606_DeleteChild
Used to delete the record specified by the @ChildId parameter from the Child
table
SP0606_InsertChild
Used to insert a record into the Child table and return the ChildId identity value
for the new record
SP0606_UpdateChild
Used to update all field values for the record in the Child table specified by the
@ChildId input parameter
SP0606_GetGrandchild
Used to retrieve a single record from the Grandchild table if the optional
@GrandchildId parameter is specified or all Grandchild records if it is not
SP0606_DeleteGrandchild
Used to delete the record specified by the @GrandchildId parameter from the
Grandchild table
SP0606_InsertGrandchild
Used to insert a record into the Grandchild table and return the GrandchildId
identity value for the new record
SP0606_UpdateGrandchild
Used to update all field values for the record in the Grandchild table specified by
the @GrandchildId input parameter
The sample code contains four event handlers and two methods:
Form.Load
Sets up the sample by creating a DataSet containing the Parent, Child, and
Grandchild DataTable objects. DataRelation objects are created relating the tables.
DataAdapter objects are created for each DataTable and the select, delete, insert,
and update Command objects are specified for each using the custom logic in the
twelve stored procedures used by this solution. The DataAdapter objects are used
to fill the tables in the DataSet. Finally, the default view of the Parent table is
bound to the data grid on the form.
CreateData( )
This method generates a number of rows in the Parent, Child, and Grandchild
DataTable objects as specified by the input parameters of the method.
UpdateData( )
This method uses the DataAdapter for each of the Parent, Child, and Grandchild
DataTable objects to update offline changes back to the database.
Create Data Button.Click
Calls the CreateData( ) to create four Parent records, four Child records for each
Parent, and four Grandchild records for each Child. Finally, the UpdateData( )
method is called to update the database with the new records.
Modify Data Button.Click
Randomly modifies or deletes records from the Parent, Child, and Grandchild
DataTable objects. The CreateData( ) method is called to create two Parent
records, two Child records for each Parent, and two Grandchild records for each
Child. Finally, the UpdateData( ) method is called to update the database with the
offline changes, deletions, and additions.
Delete Data Button.Click
Deletes all records from the Parent DataTable, which then cascades to delete all
Child and Grandchild records clearing all data from the DataSet. Finally, the
UpdateData( ) method is called to update the database with the offline deletions.
The 12 stored procedures are shown in Example 6-8
through Example 6-19.
Example 6-8. Stored procedure: SP0606_GetParent
CREATE PROCEDURE SP0606_GetParent
@ParentId int=null
AS
SET NOCOUNT ON
if @ParentId is not null
begin
select
ParentId,
Field1,
Field2
from
TBL0606Parent
where
ParentId=@ParentId
return 0
end
select
ParentId,
Field1,
Field2
from
TBL0606Parent
return 0
Example 6-9. Stored procedure: SP0606_DeleteParent
CREATE PROCEDURE SP0606_DeleteParent
@ParentId int
AS
SET NOCOUNT ON
delete
from
TBL0606Parent
where
ParentId=@ParentId
return 0
Example 6-10. Stored procedure: SP0606_InsertParent
CREATE PROCEDURE SP0606_InsertParent
@ParentId int output,
@Field1 nvarchar(50)=null,
@Field2 nvarchar(50)=null
AS
SET NOCOUNT ON
insert TBL0606Parent(
Field1,
Field2)
values (
@Field1,
@Field2)
if @@rowcount=0
return 1
set @ParentId=Scope_Identity( )
select @ParentId ParentId
return 0
Example 6-11. Stored procedure: SP0606_UpdateParent
CREATE PROCEDURE SP0606_UpdateParent
@ParentId int,
@Field1 nvarchar(50)=null,
@Field2 nvarchar(50)=null
AS
SET NOCOUNT ON
update
TBL0606Parent
set
Field1=@Field1,
Field2=@Field2
where
ParentId=@ParentId
if @@rowcount=0
return 1
return 0
Example 6-12. Stored procedure: SP0606_GetChild
CREATE PROCEDURE SP0606_GetChild
@ChildId int=null
AS
SET NOCOUNT ON
if @ChildId is not null
begin
select
ChildID,
ParentId,
Field3,
Field4
from
TBL0606Child
where
ChildId=@ChildId
return 0
end
select
ChildId,
ParentId,
Field3,
Field4
from
TBL0606Child
return 0
Example 6-13. Stored procedure: SP0606_DeleteChild
CREATE PROCEDURE SP0606_DeleteChild
@ChildId int
AS
SET NOCOUNT ON
delete
from
TBL0606Child
where
ChildId=@ChildId
return 0
Example 6-14. Stored procedure: SP0606_InsertChild
CREATE PROCEDURE SP0606_InsertChild
@ChildId int output,
@ParentId int,
@Field3 nvarchar(50)=null,
@Field4 nvarchar(50)=null
AS
SET NOCOUNT ON
insert TBL0606Child(
ParentId,
Field3,
Field4)
values (
@ParentId,
@Field3,
@Field4)
if @@rowcount=0
return 1
set @ChildId=Scope_Identity( )
select @ChildId ChildId
return 0
Example 6-15. Stored procedure: SP0606_UpdateChild
CREATE PROCEDURE SP0606_UpdateChild
@ChildId int,
@ParentId int,
@Field3 nvarchar(50)=null,
@Field4 nvarchar(50)=null
AS
SET NOCOUNT ON
update
TBL0606Child
set
ParentId=@ParentId,
Field3=@Field3,
Field4=@Field4
where
ChildId=@ChildId
if @@rowcount=0
return 1
return 0
Example 6-16. Stored procedure: SP0606_GetGrandchild
CREATE PROCEDURE SP0606_GetGrandchild
@GrandchildId int=null
AS
SET NOCOUNT ON
if @GrandchildId is not null
begin
select
GrandchildID,
ChildId,
Field5,
Field6
from
TBL0606Grandchild
where
GrandchildId=@GrandchildId
return 0
end
select
GrandchildId,
ChildId,
Field5,
Field6
from
TBL0606Grandchild
return 0
Example 6-17. Stored procedure: SP0606_DeleteGrandchild
CREATE PROCEDURE SP0606_DeleteGrandchild
@GrandchildId int
AS
SET NOCOUNT ON
delete
from
TBL0606Grandchild
where
GrandchildId=@GrandchildId
return 0
Example 6-18. Stored procedure: SP0606_InsertGrandchild
CREATE PROCEDURE SP0606_InsertGrandchild
@GrandchildId int output,
@ChildId int,
@Field5 nvarchar(50)=null,
@Field6 nvarchar(50)=null
AS
SET NOCOUNT ON
insert TBL0606Grandchild(
ChildId,
Field5,
Field6)
values (
@ChildId,
@Field5,
@Field6)
if @@rowcount=0
return 1
set @GrandchildId=Scope_Identity( )
select @GrandchildId GrandchildId
return 0
Example 6-19. Stored procedure: SP0606_UpdateGrandchild
CREATE PROCEDURE SP0606_UpdateGrandchild
@GrandchildId int,
@ChildId int,
@Field5 nvarchar(50)=null,
@Field6 nvarchar(50)=null
AS
SET NOCOUNT ON
[...]... i ) ds.Tables[PARENTTABLENAME].Rows[i - 1].Delete( ); // Update the data source with the changes UpdateData( ); MessageBox.Show("Data deleted.", "Referential Integrity" , MessageBoxButtons.OK, MessageBoxIcon.Information); } Discussion To avoid referentialintegrity problems when updating the data source from a DataSet containing related tables, use one DataAdapter for each DataTable to update the deleted,... constants for Child table private const String GRANDCHILDID_PARM = "@GrandchildId"; private const String FIELD5_PARM = "@Field5"; private const String FIELD6_PARM = "@Field6"; // private void ReferentialIntegrityUpdateLogicForm_Load(object sender, System.EventArgs e) { DataColumnCollection cols; DataColumn col; // Build the parent table DataTable parentTable = new DataTable(PARENTTABLENAME); cols... System.EventArgs e) { // Create four rows of data in each parent, child, and grandchild CreateData(4, 4, 4); // Update the data source with the new data UpdateData( ); MessageBox.Show("Data created.", "Referential Integrity" , MessageBoxButtons.OK, MessageBoxIcon.Information); } private void modifyButton_Click(object sender, System.EventArgs e) { // Randomly delete or modify rows from the grandchild, child,... parentRow.Delete( ); } // Insert two rows into parent, child, and grandchild CreateData(2 ,2, 2); // Update the data source with the changes UpdateData( ); MessageBox.Show("Data randomly modified.", "Referential Integrity" , MessageBoxButtons.OK, MessageBoxIcon.Information); } private void deleteButton_Click(object sender, System.EventArgs e) { // Delete the parent data which cascades by default // to child...update TBL0606Grandchild set ChildId=@ChildId, Field5=@Field5, Field6=@Field6 where GrandchildId=@GrandchildId if @@rowcount=0 return 1 return 0 The C# code is shown in Example 6-20 Example 6-20 File: ReferentialIntegrityUpdateLogicForm.cs // Namespaces, variables, and constants using System; using System.Configuration; using System.Windows.Forms; using System.Data; using System.Data.SqlClient; private DataSet... can be processed together in the same statement If the primary key can be modified after it has been added, the database must cascade the updated primary key values to the child records or else a referentialintegrity violation will occur The UpdateCommand property of child tables must accept either the Original or the Current value of the foreign key if it is used in the concurrency check • If the . LiB ]
Recipe 6.6 Avoiding Referential Integrity Problems When Updating the Data
Source
Problem
You sometimes get referential integrity errors when. deleted.", " ;Referential Integrity& quot;,
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
Discussion
To avoid referential integrity problems