Laden...

[gelöst] Views in Datasets mit DataGridView anzeigen

Erstellt von Bonvie vor 14 Jahren Letzter Beitrag vor 14 Jahren 1.933 Views
Bonvie Themenstarter:in
173 Beiträge seit 2006
vor 14 Jahren
[gelöst] Views in Datasets mit DataGridView anzeigen

Hallo an alle,
ich brauche mal wieder einen kleinen Anstoß da ich nicht weiterkomme.
Es geht um das Thema Views in Datasets die mit einem DataGridView angezeigt werden sollen.

Nach meinem Verständnis gibt es folgende Hierarchie:DataTabel repräsentiert die Datenbank Tabellen
DataSet entspricht einem Abbild der Datenbank im Speicher
DataGridView zeigt eine Tabelle meines DataSets an.

Ich möchte also die Datenbank auslesen, eine weile mit den Daten im Dataset arbeiten, d.h. Datensätze aktualisieren, neue einfügen oder löschen und dann später zurück schreiben.
Problem was ich habe, ist das das DataGridView leider meine Änderungen nur mit bekommt, wenn ich die Daten mit dem TableAdapter.update zurück schreibe. Was ich ja eigentlich erst viel später machen möchte.

So also hier mal meine aktuellen Schnipsel. Ich habe folgende 2 Tabellen in meiner Datenbank:

CREATE TABLE myFiles(LastUse DATETIME, UseCount INTEGER, Mark VARCHAR(40), FileSize LONG, FileDate DATETIME, FullFilename VARCHAR(255), myId AUTOINCREMENT, 
PRIMARY KEY(myId), 
UNIQUE(FullFilename))

CREATE TABLE myClip1(myId INT, WorkID INTEGER, ListId AUTOINCREMENT,
PRIMARY KEY(ListId), 
FOREIGN KEY(myId) REFERENCES myFiles(myId))

Dann habe ich mir noch mit dem VS2008 Designer eine View zusammen gebaut und diese an das dataGridView2 gebunden.

SELECT  myFiles.LastUse, myFiles.UseCount, myFiles.FullFilename, myFiles.myId, myClip1.WorkID, myClip1.ListId
FROM    myFiles INNER JOIN myClip1 ON myFiles.myId = myClip1.myId
private void button1_Click(object sender, EventArgs e)
{
    myDatabaseDataSet.myFilesRow myAktRow;
    for (int i = 0; i < (int)dataGridView1.SelectedRows.Count; i++)
    {
        myAktRow = this.myDatabaseDataSet.myFiles.FindBymyId((int)dataGridView1.SelectedRows[i].Cells[7].Value);
        myAktRow.UseCount += 1;
        this.myDatabaseDataSet.myClip1.AddmyClip1Row(myAktRow, myAktRow.myId ); // WorkId kommt später
    }
    this.myClip1TableAdapter.Update(this.myDatabaseDataSet.myClip1);
    this.myClip1ViewTableAdapter.Fill(this.myDatabaseDataSet.myClip1View);
}

Leider wird erst durch die zwei letzten Zeilen die View im DataGridView aktualisiert,
wie kann ich das anderes bzw richtig machen, das ich ohne Zugriff auf den TableAdapter das dataGridView aktualisiere.

Die Verwendung von this.myDatabaseDataSet.myClip1View.AddmyClip1ViewRow funktioniert leider auch nicht, da dort kein Paramter für myId existiert und somit immer ein neuer Eintrag in BEIDEN Tabellen vorgenommen wird.

Danke und Gruß
Bonvie

1.564 Beiträge seit 2007
vor 14 Jahren

Was macht die Funktion "this.myDatabaseDataSet.myFiles.FindBymyId"?

Wenn du hier einen Datensatz neu aus der Datenbank lädst gibt es im Speicher natürlich keine Beziehung zwischen dem neuen Datensatz und deiner bestehenden DataTable.

Normalerweise würde ich sagen verwende DataTable.LoadRow oder DataTable.Merge um die Daten in deine zweite DataTable zu übernehmen aber wenn "...da dort kein Paramter für myId existiert..." stimmt kann hier auch nix automatisch aktualisiert werden.

Ergo wirst du wohl selbst aktualisieren müssen.

Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+

Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.

J
3.331 Beiträge seit 2006
vor 14 Jahren

Hallo Bonvie,

wenn ich dich richtig verstehe, fehlt dir vor allem die laufend aktualisierte Anzeige im DataGridView. In deinen Code-Auszügen kann ich aber nichts von der Bindung des DGV an DataTable oder DataView erkennen; das solltest du wohl noch nachreichen. Auch ist unklar, wo und wie die DataView entsteht.

Nach meinem Verständnis gibt es folgende Hierarchie:
DataTabel repräsentiert die Datenbank Tabellen
DataSet entspricht einem Abbild der Datenbank im Speicher
DataGridView zeigt eine Tabelle meines DataSets an.

Nicht ganz, aber fast. Das DataSet enthält eine Menge von DataTables. DataSet und DataTable entsprechen häufig von der Struktur her der Datenbank bzw. DB-Tabelle.

Leider wird erst durch die zwei letzten Zeilen die View im DataGridView aktualisiert,

Die Aktualisierung sollte laufend geschehen. Allenfalls muss durch EndEdit die Änderung ausdrücklich abgeschlossen werden; das gilt vor allem, wenn eine BindingSource dazwischengeschoben wird (was bei dir nicht der Fall zu sein scheint).

Ich finde es übrigens seltsam, dass nach einem Update-Befehl ausdrücklich ein neuer Fill-Befehl kommen soll. Aber das hängt vielleicht mit der dort genannten DataView zusammen.

@Florian
FindBymyId und AddmyClip1Row sind Methoden des TableAdapters (typ. DataSet), die DataTable.Find und DataTable.Rows.Add für typensicheren Zugriff kapseln.

Gruß Jürgen

Bonvie Themenstarter:in
173 Beiträge seit 2006
vor 14 Jahren

@Florian Reischl
Sorry, aber ich aktualisiere doch selbst. Wenn die Tabelle Clip1 ihre Daten bekommen hat, sollte sich die View doch entsprechend verändern. Es ist ja schließlich nur eine View und keine Tabelle.

Aus meiner Sicht ist dort schon alles an updates gelaufen nur die View müsste "neu ausgeführt werden" und dann das DataGridView entsprechend befüllen. Nur passiert das aktuell noch nicht bzw. ich habe die passende Methode noch nicht gefunden.

@juetho
Die Bindung des DataGridView an DataTable hat VS2008 bei der Erstellung des DataGridView gemacht, deswegen habe ich das nicht in meinem Source. Sollte ich diese lieber manuell machen, oder was könnte an dieser Stelle falsch laufen.

private void Form1_Load(object sender, EventArgs e)
{
   // TODO: Diese Codezeile lädt Daten in die Tabelle "myDatabaseDataSet.myFiles". Sie können sie bei Bedarf verschieben oder entfernen.
   this.myFilesTableAdapter.Fill(this.myDatabaseDataSet.myFiles);

   // TODO: Diese Codezeile lädt Daten in die Tabelle "myDatabaseDataSet.myClip1View". Sie können sie bei Bedarf verschieben oder entfernen.
   this.myClip1ViewTableAdapter.Fill(this.myDatabaseDataSet.myClip1View);
}
1.564 Beiträge seit 2007
vor 14 Jahren

Hallo Jürgen

@Florian
FindBymyId und AddmyClip1Row sind Methoden des TableAdapters (typ. DataSet), die DataTable.Find und DataTable.Rows.Add für typensicheren Zugriff kapseln.

Danke für die Erläuterungen! Meinst du wirklich den TableAdapter? Ich habe gerade mal geschaut, bei mir implementiert die typisierte DataTable diese Methoden.

Grüße
Flo

Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+

Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.

J
3.331 Beiträge seit 2006
vor 14 Jahren

Hallo Florian,

Meinst du wirklich den TableAdapter? Ich habe gerade mal geschaut, bei mir implementiert die typisierte DataTable diese Methoden.

Eigentlich meinte ich das typ. DataSet. Aber der TableAdapter ist (soweit ich weiß) nur eine Erweiterung davon; deshalb hatte ich oben "TableAdapters (typ. DataSet)" geschrieben. Aber was soll's. Jürgen

1.564 Beiträge seit 2007
vor 14 Jahren

@JürgenDanke dir nochmal. Bin halt kein Profi mit typisierten DataSets...

Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+

Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.

5.299 Beiträge seit 2008
vor 14 Jahren

@Bonvie:
wie nun - zeigen die Grids gar nix an?

Ich kapier auch nicht den Zusammenhang mit deinem Select vom 1. Post nicht.
Jedenfalls ist das eine gejointe Query, und sowas kann das Dataset nicht abspeichern - wenn du es überhaupt hinkriegst, einem TableAdapter sowas unterzujubeln.
Du kannst dirmal "Datenbank in 10 Minuten" auf Movie-Tuts angugge.
Da werden auch 2 voneinander abhängige Tabellen in DGVs dargestellt.

Der frühe Apfel fängt den Wurm.

Bonvie Themenstarter:in
173 Beiträge seit 2006
vor 14 Jahren

Das erst DataGridView zeigt Daten an, aber das zweite nicht. Dies basiert auf einer Relation die ich mit dem DataSet Designer und dem INNER JOIN select Statement von oben manuell (nachträglich) angelegt habe. D.h. das zweite DataGridView soll eine Relation anzeigen, was anscheinend nicht geht bzw. wie hier beschrieben für mich erstmal zu kompliziert erscheint
http://blogs.msdn.com/msdnts/archive/2007/01/19/how-to-bind-a-datagridview-column-to-a-second-level-property-of-a-data-source.aspx

So wie ich das Ganze bisher verstanden habe kann das DataSet im Gegensatz zum DataGridView zwar eine Relation aufnehmen, nur wird diese als separate Tabelle geführt. Das würde erklären, warum erst nach dem Schreiben zur DB und dem anschließenden erneuten füllen des DataSet, die Daten im DataGridView angezeigt werden.

Kurz ich suche weiterhin, wie ich in einem DataGridView in der ich Einträge einer Child-Tabelle anzeige zusätzlich mit den passenden Parent-Objekten anzeigen kann. Da es eine 1:n Beziehung ist bleibt es logischerweise bei einer Zeile und ich brauche keine Tree-Funktionalität, die z.B. nur bei einem DataGrid möglich wäre.

Gruß
Bonvie

5.299 Beiträge seit 2008
vor 14 Jahren

Ah, nee, da muß man woanners tricksen.

Also eher Finger weg von den generierten TableAdaptern und Zeugs.

Werte aus der übergeordneten Tabelle kann man in zusätzlichen DataColumns anzeigen, mit einer Expression (=berechnete Spalte).

Kannste im Dataset-Designer anlegen, hat keinen Seiteneffekt auf den Datenbank-Zugriff.

Die Expression, diede reinschreiben musst muß der Syntax folgen, die zur DataColumn.Expression Eigenschaft inne MSDN dokumentiert ist.

Leider hat die Offline MSDN der Express-EDs diesen Eintrag nicht, müssteste dann also auf Online MSDN suchen.

Der frühe Apfel fängt den Wurm.

Bonvie Themenstarter:in
173 Beiträge seit 2006
vor 14 Jahren

Erstmal danke für deine Mühe mich hier weiter zu bringen.

Es klingt verlockend hier einfach eine Expression anzugeben, aber ich bin bis jetzt nicht über die Tabelle hinaus gekommen. Berechnungen in einer Zeile sind OK, aber wie soll eine Expressen auf eine andere Tabelle aussehen?

Dann habe ich mir überlegt, wie das überhaupt umgesetzt werden kann und denke das dann pro Spalte und Zeile ein select auf die Parent-Tabelle gemacht werden müsste, oder? Das erscheint mir als nicht der richtige (performante) Weg.

Parallel bin ich am eruieren ob LINQ hier die fehlende Funktionalität des DataSets darstellen könnte, habe aber auch noch keinen nennenswerte Erkenntnis.

Ich nehme also gerne noch weitere Lösungsvorschläge entgegen.

Schönes Wochenende
Bonvie

5.299 Beiträge seit 2008
vor 14 Jahren

Ja, du musst die Doku dazu suchen, und dir die Syntax reinziehen. Dann weißt du, wie das geht mit der Expressen auf eine andere Tabelle.

was du mit "select auf die Parent-Tabelle" meinst ist unklar. Klingt, als ob du denkst, die DataTable mache einen Datenbank-Zugriff.
Dabei folgt sie nur der im Dataset angelegten DataRelation - das sind vermutlich 2-3 Zugriffe per PropertyDescriptor oder sowas.

Mit Linq kriegste keine zusätzliche Spalte an die DataTable.

Achso - Du könntest natürlich auch eine DataGridviewComboboxColumn einbauen, die an die eigene Parent-Table gebunden ist (Üblicherweise bindet man die an andere übergeordnete Tables).

Gugge auf Movie-Tuts "M_NRelation" , das zeigt, wassich mit andere übergeordnete Table meine.

Der frühe Apfel fängt den Wurm.

Bonvie Themenstarter:in
173 Beiträge seit 2006
vor 14 Jahren

Es hat geklappt, danke für Deine ErfinderDesRades / Eure Hilfe.
Mit der folgenden MSDN Seite http://msdn.microsoft.com/en-us/library/system.data.datacolumn.expression(VS.71).aspx

war der Zugriff auf die Parent Spalte dann doch sehr leicht 😃

this.myDatabaseDataSet.myClip1.TestFilenameColumn.Expression = Parent.FullFilename

Nochmals vielen Dank
Bonvie

5.299 Beiträge seit 2008
vor 14 Jahren

no, da fehlen aberdoch die Gänsefüßchen, odr? 😉

Edit: Wie gesagt, du kannst diese Expression auch im dataset-Designer direkt eintragen.

Der frühe Apfel fängt den Wurm.