Entwickler-Ecke
Datenbanken (inkl. ADO.NET) - Scalar Queries nicht nur einen Wert zurückgeben
flyhigh83 - Mo 06.12.10 16:37
Titel: Scalar Queries nicht nur einen Wert zurückgeben
Hallo ich kenne mich mit Scalar Queries leider nicht so gut aus.
Ich habe also eine Query erstellt und folgenden Select hinterlegt.
SQL-Anweisung
1: 2: 3: 4: 5: 6: 7: 8:
| SELECT COUNT(container_has_stellplatz.chsContainer) AS AnzahlContainer, anbieter_namen.annName FROM container_has_stellplatz INNER JOIN stellplatz ON container_has_stellplatz.chsStellplatz = stellplatz.idStellplatz INNER JOIN anbieter ON stellplatz.steAnbieter = anbieter.idAnbieter INNER JOIN anbieter_namen ON anbieter.idAnbieter = anbieter_namen.annAnbieter WHERE (container_has_stellplatz.chsDatebeginn <= NOW()) AND (container_has_stellplatz.chsDateende >= NOW() OR container_has_stellplatz.chsDateende IS NULL) AND (anbieter.idAnbieter = @idStellplatz) AND (anbieter_namen.annAnsprechpartner = 1) GROUP BY anbieter_namen.annName |
Die Abfrage ist für mein Problem garnicht so wichtig vermute ich. Bisher habe ich gelesen das ScalarQueries nur einen Wert zurückgeben. In meinem Fall funktioniert dies auch. Allerdings bekomme ich bisher nur den Count Wert zurück.
Ich habe aber dieser Abfrage gleich noch mehr mitgegeben, damit ich nicht eine zusätzliche machen muss. Jetzt will ich an den Wert von anbieter_name.annName.
Wie komme ich da von dieser Abfrage ran?
Ich habe schon so sachen wie beim Datagridview versucht. "DataGridView.SelectedRows[0].Cells[17].Value.ToString()" Allerdings geht das nicht bei Abfragen.
Ralf Jansen - Mo 06.12.10 17:25
Skalare Abfragen sind explizit dafür vorgesehen nur 1 Wert zurück zuliefern(1 Zahlenwertwert ist der mathematische Kern des Begriffs Skalar). Wenn du mehr brauchst kannst du dann einfach keine skalare Abfrage benutzen da du kein skalares Problem hast. Hier solltest du dann ganz normal vorgehen per DataAdapter, DataReader, DBCommand, TableAdapter oder welche Möglichkeit dir jetzt auch immer am sympathischsten ist und dir eine DataRow bzw. Datatable liefert.
flyhigh83 - Di 07.12.10 09:13
Hi,
Den Befehl "dbCommand.ExecuteScalar()" verwende ich nicht, da ich mit den TableAdaptern von Visual arbeite.
Bisher rufe ich meinen Wert so ab.
C#-Quelltext
1:
| int AnzahlContainer = Convert.ToInt16(queriesTableAdapter.QueryCountContainer(Uebergabewert)); |
Nach dem anderen Beitrag müsste ich also etwas in der Art anlegen.
C#-Quelltext
1:
| queriesTableAdapter.QueryCountContainer NewAbfrage = new queriesTableAdapter.QueryCountContainer(); |
Allerdings habe ich kein wirkliches Objekt gefunden, welches sich erstellen läst.
Der "queriesTableAdapter" wurde bereits als Objekt erstellt, da ich diesen in mein Form gleich mit integriert habe.
Wie funktioniert dies.
flyhigh83 - Di 07.12.10 10:06
Hi,
ich bin noch gerade am rumprobieren wie ich das relativ elegant lösen kann. Mich mal an die Normalen Selects des TableAdapters herrangewagt.
C#-Quelltext
1:
| this.anbieterTableAdapter.GetData().Select("WHERE idAnbieter = 133") |
Beim Debugen bekomme ich jetzt alle Werte. Angezeigt, aber ich habe bisher noch nicht gefunden wie ich diese jetzt Abgreifen kann. Außerdem müsste ich jetzt noch auf eine UnterTabelle Zugreifen wo ich mit der ID verknüpft habe und dort ich abfragen will wer mein Ansprechpartner ist. In der Spalte "Ansprechpartner" Das Flag "True" hat.
Kann mir jemand helfen irgendwie steig ich noch nicht so wirklich durch.
Trashkid2000 - Di 07.12.10 19:22
Hallo,
probiere es mal so:
C#-Quelltext
1:
| var anbieter = this.anbieterTableAdapter.GetData().Where(x => x.idAnbieter == 133); |
Dann bekommst Du ganz einfach einen
IEnumerable zurück, den Du dann mit einer foreach duchgehen kannst.
Aber dazu müsstest Du noch "idAnbieter" mit in Dein Select nehmen, da es sonst die Property nicht gibt.
Ich denke mal auch, dass die "idAnbieter" unique ist, dann kanst Du auch sowas verwenden:
C#-Quelltext
1: 2: 3: 4: 5:
| var anbieter = this.anbieterTableAdapter.GetData().Where(x => x.idAnbieter == 133).FirstOrDefault(); if (x != null) else /Anbieter wurde nicht gefunden |
Dann bekommst Du entweder nur einen Anbieter zurück, oder wenn er nicht existiert
null
Und mit der Untertabelle und dem Ansprechpartner: Warum nimmst Du die Abfrage nicht auch noch in Dein Select- Statement auf?
Marko
flyhigh83 - Mi 08.12.10 10:50
Trashkid2000 hat folgendes geschrieben : |
Und mit der Untertabelle und dem Ansprechpartner: Warum nimmst Du die Abfrage nicht auch noch in Dein Select- Statement auf?
|
Wie ich beschrieben habe habe ich die Abfrage ja eigentlich komplett erstellt, nur wenn Sie auserhalb einer kompletten Tabelle ist, bekomme ich nur ein ScalarQuery ausgeführt.
Warum auch inmmer. Der Designer bietet mir da nichts anderes an. Wenn ich die Abfrage ausführen würde erhlate ich natürlich alle Werte, nur sehe ich diese beim Debuggen nicht. Nur im Designer wenn ich abfrage ausführen klicke.
Das Problem ist dann gewesen, wenn ich die Abfrage an eine Tabelle hänge, mekert er mir immer, das zu viele Spalten sind, oder halt die Datentypen nicht übereinstimmen. Irgend soetwas in der Richtung.
Also wenn du mir ne kleine Hilfestellung geben kannst, wäre ich Dankbar.
Irgendwie scheint das ja zu gehen, sonst hättest du deine Frage nicht so gestellt?
Danke aber für deine Hilfe hat mir schon etwas weitergeholfen.
Trashkid2000 - Mi 08.12.10 16:13
Hmm,
vielleicht wäre es ganz gut, wenn Du mal ein Bild vom Datenbankschema hier zeigst, um einfach mal zu sehen, wie denn die Daten in Verbindung stehen. Klar, man kann es auch aus dem SQL-Statement irgendwie entnehmen oder rätseln. Aber ich weiß z.B. immer noch nicht, was Du für eine Untertabelle meinst.
Marko
Trashkid2000 - Mi 08.12.10 20:45
Hallo,
habe mir mal die Arbeit gemacht, das Schema der Datenbank rauszufinden.
Meines Erachtens müsste es wie folgt aussehen:
Soweit logisch und nachvollziehbar. Aber es stellt sich mir doch die Frage, warum es eine Zwischentabelle "anbieter_namen" gibt. Denn jeder Anbieter kann doch entweder keinen (im schlimmsten Fall), einen oder mehrere Ansprechpartner haben. Oder irre ich mich da? Also eine typische 1-zu-n-Relation. Also müsste es eine Relation von "Anbieter" auf "Ansprechpartner" geben. Und die Zwischentabelle fliegt raus.
Denn in dem Zustand jetzt könnte
ein Ansprechpartner für
mehrere Anbieter existieren.
Gut, wenn wir das geklärt haben bin ich gerne bereit, weiter zu helfen!
//edit: Schema geändert
LG, Marko
flyhigh83 - Do 09.12.10 15:29
Dein Bild ist fast richtig. nur habe ich die Tabelle Ansprechpartner nicht.
Das ist einfach nur ein Spaltenname in der Tabelle "Anbieter_Name" Die Spalte kann werte vom Type Bool annehmen. Da MYSQL einfach Zahlen.
Da ich einen SerienBrief habe und jemand als Person darauf stehen haben will, habe ich dieses Feld eingefügt.
Das, wenn ich automatisch den Anbieter habe er mir dann den Anbieter sucht, welcher die ID des Anbiters hat und in der Spalte Ansprechpartner den Wert "1" stehen hat.
Vielen Dank für deine Mühe. Muss noch bissel was für die FH machen werde mir aber heute spätestens morgen deine Antwort ansehen, solltest du dazu kommen.
Trashkid2000 - Do 09.12.10 20:37
Hi,
da habe ich es ja (fast) richtig verstanden. Habe oben mal das Schema aktualisiert.
Du möchtest also eine Abfrage starten, welcher Ansprechpartner für wie viele Container zuständig ist, oder?
Also, Du hast nun also so eine DataTable:

(habe mal die DataTable, den TableAdapter und die Properties umbenannt)
Dann ergibt sich dieser Code:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| DataSet1 ds = new DataSet1(); ansprechpartnerTableAdapter tableAdapter = new ansprechpartnerTableAdapter(); tableAdapter.Fill(ds.ansprechpartner);
foreach (DataSet1.ansprechpartnerRow ansprechpartner in ds.ansprechpartner) { Console.WriteLine(string.Format("Ansprechpartner: {0}", ansprechpartner.AnsprechpartnerName)); Console.WriteLine(string.Format("Anzahl der betreuten Container: {0}", ansprechpartner.AnzahlContainer)); } |
Hoffe, dass es Dir weiterhilft bzw. das ist, was Du wolltest!
LG, Marko
flyhigh83 - Mi 15.12.10 17:26
Puh endlich bin ich dazugekommen heute dies etwas zu testen. Bisher habe ich immer noch nichts brauchbares herrausgefunden.
Danke für deine Anweisung, aber das wäre ja für eine Abfrage welche bereits an einem DataTable hängt. Wie das funktioniert ist mir klar.
Der Designer sagt mir nur immer wenn ich weitere Felder habe die nicht zu dem DataTable passen, das man dies vermeiden soll. Irgend so eine Warnung. Leider führt er mir wenn es dazu kommen soll dann die Abfrage nicht aus.
Ich glaube was mir ganz einfach weiterhelfen kann ist, gibt es eine Möglichkeit einen DataTable zu erstellen welche Beliebig ist von den Feldern, so das ich meine Abfrage einfach anhängen kann. Oder welche möglichkeiten gibt es da.
Ich versuche gerade so sachen.
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
| string selectCommand = "SELECT COUNT(container_has_stellplatz.chsContainer) AS AnzahlContainer, anbieter_namen.annName" + "FROM container_has_stellplatz INNER JOIN" + " stellplatz ON container_has_stellplatz.chsStellplatz = stellplatz.idStellplatz INNER JOIN" + " anbieter ON stellplatz.steAnbieter = anbieter.idAnbieter INNER JOIN" + " anbieter_namen ON anbieter.idAnbieter = anbieter_namen.annAnbieter" + "WHERE (container_has_stellplatz.chsDatebeginn <= NOW()) AND (container_has_stellplatz.chsDateende >= NOW() OR" + " container_has_stellplatz.chsDateende IS NULL) AND (anbieter.idAnbieter = @idStellplatz) AND (anbieter_namen.annAnsprechpartner = 1)" + "GROUP BY anbieter_namen.annName";
String connectionString = "server=192.168.0.1;User Id=test;database=test;password=test;Persist Security Info=True";
dataAdapter = new MySqlDataAdapter(selectCommand, connectionString);
MySqlCommandBuilder commandBuilder = new MySqlCommandBuilder(dataAdapter);
DataTable table = new DataTable(); table.Locale = System.Globalization.CultureInfo.InvariantCulture; dataAdapter.Fill(table); |
Allerdings gibt es noch einen Fehler bei "dataAdapter.Fill(table)". Ich weis der Code ging mal. Hoffe das ist nicht auch schon wieder von Avira :-)
Das andere Problem was ich mit diesem Code hätte. Er ist nicht so ganz mein Fall, da ich eigentlich mit den DataTablesAdaptern gearbeitet habe und dann nicht so ganz ins Bild Passt. Bin für jeden weiteren Tip dankbar.
Trashkid2000 - Mi 15.12.10 23:49
Hallo,
so langsam verstehe ich das Problem nicht mehr!
Also, wenn Du im Designer einen neuen Tableadapter mit Deiner Sql-Anweisung erzeugst, dann wird die entsprechende DataTable mit erzeugt. Alle Spalten, die Du in der Sql-Anweisung abfragst, sind auch als Spalten in der DataTable. Automatisch. So kann es auch nicht vorkommen, dass Du Spalten abfragst, die nicht in der Table vorkommen. Und somit ist das Füllen auch kein Problem. Und somit braucht Du im Code dann nur noch das Füllen der Table erledigen.
Weiss nicht, was ich sonst noch dazu sagen soll :nixweiss:
Marko
flyhigh83 - Do 16.12.10 09:39
Morgen Trashkid2000
Danke für deine Hilfe. Mit Probieren und einer Nacht hat es geholfen.
Irgend etwas macht der Designer anders wenn man eine Abfrage einfach hinzugfügt. Da kann man ja nur ScalarQueries auswählen. Diese geben egal wie immer nur einen Wert zurück Egal ob man eine Abfrage macht mit mehreren Spalten oder Datensätzen.
Jetzt habe ich einfach mal einen neuen TableAdapter hinzugefügt und einfach nur eine Abfrage erstellt. Jetzt geht es. :-)
Sollte dies kein sauberer Programmierstil sein, ich nehme gerne Hilfe an wie man sowas sauber macht. So muss weiter dem Prof zuhören.
Trashkid2000 - Do 16.12.10 22:36
flyhigh83 hat folgendes geschrieben : |
Sollte dies kein sauberer Programmierstil sein, ich nehme gerne Hilfe an wie man sowas sauber macht. |
Ich weiß nicht, was daran nicht sauber sein sollte. Ich meine, ob Du nun bei einem TableAdapter die Standard-Selectanweisung (
SELECT * FROM xxx;) generieren lässt, oder Deine eigene Select-Anweisung definierst, ist ja nun wirklich egal!
Marko
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!