Hierarchial update of Master/Child with identity not possible

10/10/2009 - 11:53 von Christoph Wohlan | Report spam
Hi all,

wie ich das sehe, habe ich das selbe Problem wie es Sven bereits im
Juni hier beschrieben hat, bzw. wie es in dem von Frank Dzaebel
geposteten Link "Hierarchial update of Master/Child with autoincrement
(identity) primary key on Master - not possible" beschrieben ist. An
der Datenbank liegt's jedenfalls nicht!

On 1 Jun., 12:35, Sven Thierfelder <nu...@sd-thierfelder.de> wrote:

Hi all

ich arbeite mit VS2008. Wenn ich ein typisiertes Dataset anlege,
[...] Dann werden die neuen ID's aus Tabelle A
richtigerweise in gültige ID's in der Datenbank getauscht, doch die ID's in
der untergeordneten Tabelle B bleiben unberührt. So wie ich das in den
Beispielen verstanden habe, sollte dies eben nicht passieren. Die Beziehung
der Tabellen ist ordnungsgemàß angelegt. [...] ich habe nach den Updates eine
inkonsistente Datenbank.
Was mache ich denn falsch?

Gruß Sven



Der Testaufbau (Vista, SQLServer 2005, VS 2005, .Net 3.5 SP1) ist
folgender: 2 Tabellen center und department (Master/Child) und eine
Stored Procedure "InsertIntoMaster" mit SCOPE_IDENTITY() als
Rückgabewert. Ein typisiertes DataSet mit den beiden Tabellen und
einer entsprechenden Relation mit alle Cascades die man einschalten
kann. Ich arbeite mit "einfachen" DataAdaptern und nicht mit
TableAdaptern. In der DataSet.cs zur DataSet.xsd steht der zusàtzliche
Code:

partial class DataSet
{
private SqlConnection connection;

private SqlDataAdapter centerDataAdapter;
private SqlDataAdapter departmentDataAdapter;

public void Init()
{
SqlCommand cmd = null;

this.connection = new SqlConnection
(Properties.Settings.Default.ConnectionString);

// Center (Master)
this.centerDataAdapter = new SqlDataAdapter("Select centerid,
center from center", this.connection);
this.centerDataAdapter.MissingSchemaAction MissingSchemaAction.AddWithKey;

SqlCommandBuilder commandBuilder = new SqlCommandBuilder
(this.centerDataAdapter);
this.centerDataAdapter.UpdateCommand commandBuilder.GetUpdateCommand();
this.centerDataAdapter.DeleteCommand commandBuilder.GetDeleteCommand();

this.centerDataAdapter.InsertCommand = new SqlCommand
("InsertCenter", this.connection);
this.centerDataAdapter.InsertCommand.CommandType CommandType.StoredProcedure;
this.centerDataAdapter.InsertCommand.UpdatedRowSource UpdateRowSource.Both;
this.centerDataAdapter.InsertCommand.Parameters.Add("@center",
SqlDbType.NChar, 2, "center");
this.centerDataAdapter.InsertCommand.Parameters.Add
("@centerid", SqlDbType.Int, 0, "centerid");
this.centerDataAdapter.InsertCommand.Parameters
["@centerid"].Direction = ParameterDirection.Output;

this.centerDataAdapter.RowUpdated += new
SqlRowUpdatedEventHandler(centerDataAdapter_RowUpdated);

// Department (Child)
this.departmentDataAdapter = new SqlDataAdapter("Select
departmentid, centerid, department from department", this.connection);
this.departmentDataAdapter.MissingSchemaAction MissingSchemaAction.AddWithKey;

SqlCommandBuilder commandBuilder = new SqlCommandBuilder
(this.departmentDataAdapter);
this.departmentDataAdapter.UpdateCommand commandBuilder.GetUpdateCommand();
this.departmentDataAdapter.DeleteCommand commandBuilder.GetDeleteCommand();

this.departmentDataAdapter.InsertCommand = new SqlCommand
("InsertDepartment", this.connection);
this.departmentDataAdapter.InsertCommand.CommandType CommandType.StoredProcedure;
this.departmentDataAdapter.InsertCommand.UpdatedRowSource UpdateRowSource.Both;
this.departmentDataAdapter.InsertCommand.Parameters.Add
("@centerid", SqlDbType.Int, 0, "centerid");
this.departmentDataAdapter.InsertCommand.Parameters.Add
("@department", SqlDbType.NChar, 2, "department");
this.departmentDataAdapter.InsertCommand.Parameters.Add
("@departmentid", SqlDbType.Int, 0, "departmentid");
this.departmentDataAdapter.InsertCommand.Parameters
["@departmentid"].Direction = ParameterDirection.Output;
}

public void Fill()
{
this.center.Clear();
this.centerDataAdapter.Fill(this.center);

this.department.Clear();
this.departmentDataAdapter.Fill(this.department);
}

public void UpdateCenter()
{
DataTable changes = this.center.GetChanges();
if (changes != null)
{
this.centerDataAdapter.Update(changes);
this.center.Merge(changes, true,
MissingSchemaAction.AddWithKey);
}
}

void centerDataAdapter_RowUpdated(object sender,
SqlRowUpdatedEventArgs e)
{
/* liest die neue centerid nach dem Update einwandfrei in e.Row
["centerid", DataRowVersion.Current]
* ... aber Laufzeitfehler: centerid ist schreibgeschuetzt !!!
if (e.Status == UpdateStatus.Continue && e.StatementType =StatementType.Insert)
{
e.Row["centerid"] = Convert.ToInt32(e.Row["centerid",
DataRowVersion.Current]);
e.Row.AcceptChanges();
}
*/
}

public void UpdateDepartment()
{
DataTable changes = this.department.GetChanges();
if (changes != null)
{
this.departmentDataAdapter.Update(changes);
this.department.Merge(changes, true,
MissingSchemaAction.AddWithKey);
}
}
}

Das Windows-Form hat dataSet, centerBindingSource,
departmentBindingSource (mit centerBindingSource-center$department als
Datenquelle),
centerDataNavigator, die Textboxen centerid und center sowie ein
departmentDataGridView:

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.dataSet.Init();
this.dataSet.Fill();
}

private void departmentBindingSource_AddingNew(object sender,
AddingNewEventArgs e)
{
this.centerBindingSource.EndEdit();
}

private void centerBindingNavigatorSaveItem_Click(object sender,
EventArgs e)
{
this.Validate();

this.centerBindingSource.EndEdit();
this.departmentBindingSource.EndEdit();

this.dataSet.UpdateCenter();
this.dataSet.UpdateDepartment();

this.dataSet.AcceptChanges();
}
}

Ich öffne 2 Instanzen gleichzeitig und lege erst ein neues center (id
1) mit zwei neuen departments (id-centerid 1-1, 2-1) an. Update! Ok!
Anschliessend lege ich mit der anderen Instanz das nàchste center (id
1) mit zwei neuen departments (id-centerid: 1-1, 2-1). Wieder Update!
Die neue centerid kommt in e.Row["centerid", DataRowVersion.Current]
zurück, wird aber nicht übernommen, bzw. in die departments
übertragen. CASCADE funktioniert nicht??? Gespeichert wird tatsàchlich
das neue center (id 2) mit zwei departments zum ersten center (id-
centerid: 3-1, 4-1). CASCADE funktioniert nicht!!!

Gibt es inzwischen eine Lösung? Mache ich was falsch? Gibt es einen
vernünftigen workaround?

Ich danke Euch im voraus für Eure Hilfe.

Grüße Christoph
 

Lesen sie die antworten

#1 Peter Fleischer
10/10/2009 - 14:11 | Warnen spam
"Christoph Wohlan" schrieb im Newsbeitrag
news:

Gibt es inzwischen eine Lösung? Mache ich was falsch? Gibt es einen
vernünftigen workaround?



Hi Christoph,
bei mir funktioniert es problemlos. Es gibt zwei Dinge zu beachten, die aus
deinem Code nicht ersichtlich sind:

- kaskadierte Aktualisierungsweitergabe im DataSet muss eingeschaltet sein,
damit die Fremdschlüsselwerte auch richtig eingetargen werden, wenn für den
Master-datensatz im OnRoeUpdated der Primàrschlüssel geàndert wird;
- neue Eintràge sind zuerst in der Master-Tabelle einzutragen und erst
danach in der Child-Tabelle, damit auch die richtigen Werte in der Datenbank
abgelegt werden.

Viele Gruesse

Peter

Ähnliche fragen