Here I will post problems I and my colleagues met and solutions we found.

Thursday, February 24, 2005

Insert into dependent parents II

So, since I had to insert data into table contacts first, insert data into table contact_addresses next and update table contacts after that, why not to try to do it just in application itself, not in SQL statements.

I read help files and found that all I had to do is to use GetChanges() method get new rows from table contast, use DataAdapter to update them. Then Update rows from table addresses and then update rows from contacts again, even if they were inserted before.

Whell, it did not work. Here is why.

What I did was:

DataTable newContacts = contactsTabe.GetChanges(DataRowState.Add);
contactsDataAdapter.Update(newContacts);
addressesDataAdapter.Update(addressesTable);
contactDataAdapter.Update(contacsTable);

Now what GetChanges() method does? It creates Clone for table, and this table does not belong to DataSet!!! All rows are copies of rows from contactsTable. It had two effects.
1) When new Id values were returned from server, there were no information about any DataRelations, so these Id values were not propagated to child records.
2) These values were not returned to contactTable.

Then I used different approach which is the last one. At least so far.

1. Update
SetInsertOnly(true);
try
{

contactsDataAdapter.InsertCommand =
contactsInsertCommand;

contactsDataAdapter.Update(dataSet, "contacts");
}
finally
{

SetInsertOnly(false);
}
addressDataAdapter.Update(dataSet, "contact_addresses");
// know update the rest
contactsDataAdapter.InsertCommand = contactsUpdateCommand;
contactsDataAdapter.Update(dataSet, "contacts");


2.In RowUpdating event handler

if (insertOnly)
{

if (e.StatementType != StatementType.Insert)
e.Status = UpdateStatus.SkipCurrentRow;
}
Using this flag I indicated that only new rows would be affected in insert only mode. SQL stamtement in this case was very simple, just creating record in table contacts and getting id.
3.in RowUpdated event handler in InsertOnly mode I set

if (e.StatementType == StatementType.Insert)
e.Status = UpdateStatus.SkipCurrentRow;

This way row was not marked as updated because AcceptChanges was not called.

4. For adresses RowUpdated event handler
if (e.StatementType == StatementType.Insert)
{
if (e.Row.HasVersion(DataRowVersion.Original))
{

DataRow r = e.Row.GetParentRow(e.Row.Table.ParentRelations[0]);
if (r != null)
{
object val = r["primary_address_id"];
if (!Convert.IsDBNull(val))
{
if (Convert.ToInt32(val) == Convert.ToInt32(e.Row["contact_address_id",
DataRowVersion.Original]))
r["primary_address_id"] =
e.Row["contact_address_id", DataRowVersion.Current];
}
}
}
}


This was to get new primary_id values
from contact_addresses table to contact table.

BTW, cannot save formatting for source code. This blogs just clears all spaces at the beginning of lines :(

No comments: