Laden...

Immer wieder Databinding und Relations

Erstellt von buyden vor 15 Jahren Letzter Beitrag vor 15 Jahren 1.561 Views
B
buyden Themenstarter:in
203 Beiträge seit 2007
vor 15 Jahren
Immer wieder Databinding und Relations

verwendetes Datenbanksystem: <MySql5>

Ich weiß, das das Thema schon etliche Male behandelt wurde aber trotzdem bin ich noch nicht so richtig dahinter gestiegen und auch in Büchern wird die Geschichte meist nicht all zu genau erklärt.

Ich habe die angehängte gui zur Verwaltung von Kontakten.
ich habe ein DataSet mit den Tabellen kontakte, adresse, ort, land, anrede.
Diese habe ich mittels Relation verknüpft:


//Relations
dsDB.Relations.Add(new DataRelation("fk_adresse_kontakte", dsDB.Tables["kontakte"].Columns["idkontakte"], dsDB.Tables["adresse"].Columns["kontaktid"]));
dsDB.Relations.Add(new DataRelation("fk_ort_adresse", dsDB.Tables["ort"].Columns["idort"], dsDB.Tables["adresse"].Columns["ort"]));
dsDB.Relations.Add(new DataRelation("fk_anrede_kontakte", dsDB.Tables["anrede"].Columns["idanrede"], dsDB.Tables["kontakte"].Columns["anrede"]));
dsDB.Relations.Add(new DataRelation("fk_land_ort", dsDB.Tables["land"].Columns["idland"], dsDB.Tables["ort"].Columns["land"]));

Für jede Tabelle gibt es eine BindingSource.
Das linke DataGridView ist an die bsKontakte gebunden, das rechte an bsAdresse.
Die TextBoxen und Comboboxen sind an die entsprechenden BindingSources gebunden.
Jetzt sollen sämtliche Felder aktualisiert werden, wenn im linken Grid ein Eintrag ausgewählt wurde.
Ich kenne von Delphi, dass bei verknüpften Tabellen der Zeiger automatisch gesetzt wird.
Ist nicht eine Relation dazu da, den Zeiger in der verknüpften Tabelle den auf den entsprechenden Eintrag der Master-Tabelle zu setzen? Ich habe mir geholfen, indem ich beim Wechsel des Currents einer BindingSource das entsprechende Feld in der Detailtabelle auswähle:


private void bsKontakte_CurrentChanged(object sender, EventArgs e)
{
   if (BindingComplete)
   {
      bsAdresse.Filter = "kontaktid = " + ((DataRowView)bsKontakte.Current).Row["idkontakte"].ToString();
      bsAnrede.Position = bsAnrede.Find("idanrede", ((DataRowView)bsKontakte.Current).Row["anrede"].ToString());
   }
}

Das funktioniert zwar, ist aber bei vielen verknüpften Tabellen kaum realisierbar, finde ich.
Stimmt mein Ansatz so oder mach ich grundsätzlich was falsch? Ich kann ja auch nicht einfach mit Drag&Drop alles zusammenklicken, wie das in vielen Tuts gemacht wird, da ich mit MySql kein typisiertes Dataset zur Entwurfszeit erstellen kann - oder?

4.221 Beiträge seit 2005
vor 15 Jahren

Ich habe noch nie mit BindingSource gearbeitet (sondern nur mit den Mechanismen welche es schon in 2003 gab).

Vermutlich ist die Child-Seite falsch gebunden.

Versuche mal die Child-Seite so oder so ähnlich zu binden:

Falsch: ChildTable

Richtig: ParentTable.Relation

Wie es genau im Detail funzt musst Du allerdings selber rausfinden...

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

5.299 Beiträge seit 2008
vor 15 Jahren

Hi!

Vllt. ist das des Pudels Kern:
AddresseBindingSource.DataSource darf nicht die Addresse-DataTable des Datasets sein, sondern muß KontakteBindingSource sein.
Außerdem muß .DataMember auf "fk_Kontakt_Addresse" gesetzt sein.

Ich kann ja auch nicht einfach mit Drag&Drop alles zusammenklicken, wie das in vielen Tuts gemacht wird, da ich mit MySql kein typisiertes Dataset zur Entwurfszeit erstellen kann - oder?

Klar kannst du. Dem Projekt ein Dataset hinzufügen, und selbiges im Dataset-Designer einrichten (Tabellen und Relations dran machen).
Du kannst es dir nicht fixnfertig aus der DB generieren lassen, und es generiert dir auch keine TableAdapter.
Aber für Databinding im Designer isses voll tauglich.

Der frühe Apfel fängt den Wurm.

B
buyden Themenstarter:in
203 Beiträge seit 2007
vor 15 Jahren

@Erfinderdesrades

Das werde ich mal versuchen, aber heut nicht mehr 😉

4.221 Beiträge seit 2005
vor 15 Jahren

Du willst ja nicht auf die ganze Tabelle binden... sondern auf die Children des Parents.

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

B
buyden Themenstarter:in
203 Beiträge seit 2007
vor 15 Jahren

So weit, so gut...

AddresseBindingSource.DataSource darf nicht die Addresse-DataTable des Datasets sein, sondern muß KontakteBindingSource sein.
Außerdem muß .DataMember auf "fk_Kontakt_Addresse" gesetzt sein.

Hab ich gemacht und scheint zu funktionieren. Jetzt hat aber die Tabelle adresse auch noch einen Fremdschlüssel zur Tabelle ort, also müsste ich ja für bsAdresse als DataSource jetzt bsOrt angeben und den fk_ort_adresse als DataMember, kann ich ja aber nicht weil die Eigenschaften ja schon vergeben sind. - Was nun?

5.299 Beiträge seit 2008
vor 15 Jahren

Das ist dann wohl eine m:n - Relation, und dein View geht:
abwärts (Parent-Child): Kontakt->Addresse
aufwärts (MasterDetail): Addresse->Ort

aufwärts bedeutet: es werden nicht anhand des Primkeys alle Children eines Datensatzes gesucht, sondern anhand eines ForeignKeys der einzige Parent-Datensatz eines untergeordneten.

Anzeigen tut man das in Comboboxen, für jede Spalte, die man vom Parent benötigt, eine.
Beim EinzelblattView nimmste richtige Comboboxen, innerhalb eines Grids ComboboxColumns.

Kannstedir angucken auf Movie-Tuts, "M_N_Relation".

Ansonsten tätich jetzt mal langsam ein typisiertes Dataset empfehligen - die ganzen Spalten, Tabellen, Relations händisch korrekt einzurichten scheint mir total mühsam, unübersichtlich und riskant, und im Ergebnis haben deine Daten-Objekte immer nur Datentyp Object, und müssen bei jeder Verwendung erstmal gecastet werden, was auch immer eine Fehlerquelle ist, die der Compiler nicht überprüfen kann.

Der frühe Apfel fängt den Wurm.

B
buyden Themenstarter:in
203 Beiträge seit 2007
vor 15 Jahren

Hab mir jetzt ein typisiertes DS gebastelt und die Zusammenklickserei funktioniert auch soweit ganz gut.
Allerdings bekomm ich's nicht hin, die Comboboxen für Ort, PLZ und Land so zu binden, dass das angezeigt wird, was man erwartet, nämlich der Ortsname des aktuellen Adress-Datensatzes und als Dropdown alle verfügbaren Ortsnamen. In der DataGridViewComboBoxColumn geht das ja auch.

B
buyden Themenstarter:in
203 Beiträge seit 2007
vor 15 Jahren

hier das ganze nochmal in der IDE

5.299 Beiträge seit 2008
vor 15 Jahren

In der DataGridViewComboBoxColumn geht das ja auch.

Ja, und mitte normalen Combo gehts fast genau so.
Im Form-Designer halt DataSource, DisplayMember, ValueMember richtig einstellen, und dann noch den (DataBindings)-Knoten erweitern, und dort SelectedValue an die OrtID der AddressBindingSource binden.

Vergleichbares ist hier gemacht: SingletonDataset

Edit: Das Land macht aber Probleme.

Ach nee, vllt nicht:
Wenn Ort-Combo eine eigene BindingSource kriegt, müsste man mit der Land-Combo eigentlich dasselbe machen können wie mit der Ort-Combo.

Der frühe Apfel fängt den Wurm.

B
buyden Themenstarter:in
203 Beiträge seit 2007
vor 15 Jahren

Naja hier wären vielleicht gleiche Bezeichner für die gleichen Eigenschaften angebracht gewesen.

Die Ort-Combos funzen. Allerdings hab ich festgestellt, dass totaler Müll angezeigt wird, wenn ich die Combos mit DisplayMember und ValueMember direkt an die Tabelle im Dataset binde, da hatte Kontakt 2 den Ort von Kontakt 1 usw. Jetzt hab ich an die ortBindingSource gebunden, und es geht.
Die Land-Combo macht aber doch Probleme, es wird zwar angezeigt, aber beim Wechsel zwischen den Adressen, also auch den Orten wird Land nicht aktualisiert.
DataSource: landBindingSource
DisplayMember: name
ValueMember: idland
SelectedValue: ortBindingSource.land

Ich vermute der Grund ist das die BindingSources von Adresse und Ort nicht so verknüpft sind wie bei Kontakte und Adresse oder?

5.299 Beiträge seit 2008
vor 15 Jahren

Hmm, ich hab kein Problem damit:

Der frühe Apfel fängt den Wurm.

B
buyden Themenstarter:in
203 Beiträge seit 2007
vor 15 Jahren

Hmm, der einzige Unterschied, den ich feststellenkonnte ist, dass bei meiner Beziehung nicht die Fremdschlüsseleinschränkungen aktiviert sind, tue ich das bekomm ich eine ConstraintException aber ich weiß nicht wo genau.

5.299 Beiträge seit 2008
vor 15 Jahren

So Constraint-Exceptions kriegt man z.B. beim Laden, wenn man untergeordnete Tabellen von ihren Parents lädt.

eine Möglichkeit

Der frühe Apfel fängt den Wurm.

B
buyden Themenstarter:in
203 Beiträge seit 2007
vor 15 Jahren

ich hab jetzt nochmal die Reihenfolge der Fill-Befehle umgeschlichtet, bekomme jetzt auch mit Fremdschlüseleinschränkungen keine ConstraintExeption mehr aber die Land-Combo aktualisiert trotzdem nicht. Allerdings wird die scheinbar aktualisiert, wenn ich den "Persönliche Daten"-Tab aktiviert hab und den Kontakt wechsele, das allerdings auch nicht immer. Wenn ich dann zum "Adresse"-Tab wechsele und wieder die Kontakte umschalte, bleibt die Land-Combo dann beim ersten Wert stehen. Die Land-Combo ist grundsätzlich genau so gebunden, wie die anderen, aber die einzige, die nicht funktioniert.