Shadowman Geschrieben 22. Juli 2014 Geschrieben 22. Juli 2014 Hallo zusammen, ich habe mir eine Klasse gebaut, mit der ich auf eine Datenbank zugreife. In der Klasse gibt es folgende Methoden: public void prepare(string query) public void addParam(string key, string val) public void execute() public bool fetch(ref DbDataReader ret) public DbDataReader fetch() public void close() für einzelne Rückgaben verwende ich die fetch Methode, welche einen bool wert liefert, bei mehreren Ergebnissen möchte ich die Methode jedoch so ansprechen können (die erste Methode wird danach gelöscht, da ich es dann wie unten bloß ohne das while machen kann): while (data = db.fetch()) { // mach etwas } Hier bekomme ich jedoch einen compiler Fehler: Eine implizite Konvertierung vom Typ "System.Data.Common.DbDataReader" in "bool" ist nicht möglich. Hat jemand einen Tip für mich, wie ich die Funktion fetch aufbauen muss, damit eine solche Verwendung möglich ist? Ich stehe da total aufm Schlauch. Danke schonmal! Mfg Shadowman Zitieren
lbm1305 Geschrieben 22. Juli 2014 Geschrieben 22. Juli 2014 Nun...zuerst liefert Dir die 'fetch' Methode ein Objekt vom Typ 'DbDataReader'. data ist sicherlich vom Typ 'Boolean'. Und wie es die Meldung bereits mitteilt, kann ein DbDataReader nicht in ein bool umgewandelt werden. Man kann die enthaltenen Zeilen eine DataReader mit einer while-Schleife durchlaufen. am Beispiel eines SqlDataReaders: SqlDataReader.Read-Methode (System.Data.SqlClient) Zitieren
Shadowman Geschrieben 22. Juli 2014 Autor Geschrieben 22. Juli 2014 sorry, diese Zeile habe ich leider vergessen zu kopieren: DbDataReader data = null; ich möchte den Reader eben per while durchlaufen, jedoch jede Zeile einzeln ansprechen können. Aus diesem Grund sieht der Methodenaufruf so aus: while (data = db.fetch()) { permission t_permission; t_permission.group = "user"; t_permission.name = data["name"].ToString(); t_permission.value = data["value"].ToString(); this.permissions.Add(t_permission); } Zur Klasse: OdbcDataReader reader; Die Methode fetch sieht so aus: public DbDataReader fetch() { if (!error.f()) { if (this.reader.Read()) return reader; else return null; else return null; } error.f() gibt nur zurück, ob vorher ein Fehler aufgetreten ist (in diesem Fall false). Zitieren
Guybrush Threepwood Geschrieben 22. Juli 2014 Geschrieben 22. Juli 2014 while verlangt einen bool Ausdruck und wie die Fehlermeldung ja schon sagt kann DbDataReader nicht implizit in bool umgewandelt werden. Du musst z.B. prüfen ob null zurückkommt oder nicht. Zitieren
Shadowman Geschrieben 22. Juli 2014 Autor Geschrieben 22. Juli 2014 Aber ich prüfe doch garnicht, ob fetch() den datentyp bool zurück gibt, sondern ob die Anweisung (data = fetch()) == true ist? oder müss ich dafür den = operator von fetch überladen? Zitieren
Klotzkopp Geschrieben 22. Juli 2014 Geschrieben 22. Juli 2014 Aber ich prüfe doch garnicht, ob fetch() den datentyp bool zurück gibt, sondern ob die Anweisung (data = fetch()) == true ist?Wann ist denn ein Zuweisungsausdruck true? Wenn die Zuweisung geklappt hat, oder wie stellst du dir das vor? Ein Zuweisungsausdruck hat den Wert des Ziels. Wenn du prüfen willst, ob das Ziel null ist, musst du das schon hinschreiben. Zitieren
Shadowman Geschrieben 22. Juli 2014 Autor Geschrieben 22. Juli 2014 In der Berufsschule wurde uns damals gesagt, dass eine Variablenzuweisung immer true zurück gibt, da es kein Vergleichsoperator ist, sondern ein Zuweisungsoperator. Im Grunde möchte ich nur Zeilenweise das fetch() (und somit auch den reader) durchlaufen, bis kein Ergebnis mehr kommt und gleichzeitig die Readerzeile einer Variable zuweisen. Also bleibt mir wohl nichts anderes übrig, als es wie bisher mit dieser Variante zu machen: public bool fetch(ref DbDataReader ret) Zitieren
Klotzkopp Geschrieben 22. Juli 2014 Geschrieben 22. Juli 2014 In der Berufsschule wurde uns damals gesagt, dass eine Variablenzuweisung immer true zurück gibt, da es kein Vergleichsoperator ist, sondern ein Zuweisungsoperator.Das ist falsch. Wenn der Wert von vornherein feststünde, wäre er überflüssig. Außerdem könnte man Zuweisungen dann nicht mehr verketten. Im Grunde möchte ich nur Zeilenweise das fetch() (und somit auch den reader) durchlaufen, bis kein Ergebnis mehr kommt und gleichzeitig die Readerzeile einer Variable zuweisen.Dann prüf deinen Zuweisungsausdruck auf != null. Zitieren
Shadowman Geschrieben 22. Juli 2014 Autor Geschrieben 22. Juli 2014 (bearbeitet) meinst du so if((data = db.fetch()) != null) oder so data = db.fetch(); do { // mach etwas data = db.fetch(); } while(data != null); Bearbeitet 22. Juli 2014 von Shadowman Zitieren
lbm1305 Geschrieben 22. Juli 2014 Geschrieben 22. Juli 2014 Uuhhh...bei dem do-while wird einem ja schlecht. warum nicht so? //Pseudocode var reader = db.fetch(); if (reader == null || !reader.HasRows) { return; } while (reader.Read()) { var ordinal = reader.GetOrdinal("NamederSplate"); var result = reader.GetInt32(ordinal); } Zitieren
Shadowman Geschrieben 22. Juli 2014 Autor Geschrieben 22. Juli 2014 Ich mag auch keine do-while schleifen! Ganz ekeliges Zeug Ich wollte die Verwendung der Rückgabewerte auf ein absolutes minimum beschränken, genauso wollte ich nichts über den Reader mit aus der Klasse geben. Das Objekt was ich rausschicke (unter Umständen wird sich das nämlich verändern und dann verwende ich möglicherweise keinen Typ mit einem Read() mehr) soll komplett über eigene Methoden angesprochen werden, wegen der Polymorphie. Nennen wir es einfach mal persönliche Gründe Zitieren
SilentDemise Geschrieben 22. Juli 2014 Geschrieben 22. Juli 2014 Das macht allerdings nicht so wirklich sinn. Zitieren
Shadowman Geschrieben 23. Juli 2014 Autor Geschrieben 23. Juli 2014 Ein bisschen genauere Aussagen wären vielleicht sogar hilfreich Zitieren
lbm1305 Geschrieben 23. Juli 2014 Geschrieben 23. Juli 2014 Sorry...der Code sagt nichts darüber aus, was Du mit der Klasse, die eh zuviel macht, erreichen möchtest. Auch das Eröffnungspost lässt darauf nicht schließen. Du sagst, du willst keine Reader rausgeben? Aber was macht die Fetch-Methode ohne Parameter? Wenn Du das Ziel, welches Du erreichen möchtest, entweder durch Pseudocode oder mit Sätzen genauer beschreiben könntest, wäre Dir sicherlich mehr geholfen. Zitieren
Shadowman Geschrieben 23. Juli 2014 Autor Geschrieben 23. Juli 2014 (bearbeitet) Die Klasse soll über wenige Schnittstellen beliebige Datenbankabfragen ausführen und die Ergebnisse zurückgeben können. Zusätzlich muss es möglich sein mit Hilfe von Abstraktion unterschiedliche Datenbanksysteme anbinden zu können. Über die Methode prepare wird das entsprechende SQL-Statement übergeben, welches Platzhalter enthalten kann. Platzhalter werden mit der Methode addParam an die Klasse übergeben und vor dem execute in das Statement eingebaut. Execute stellt die Verbindung zur Datenbank her und stellt intern einen Reader bereit, welcher dann Zeilenweise über die Methode fetch() durchlaufen werden kann. Zum Abschluss terminiert die Methode close die Datenbankverbindung. Die unterschiede der beiden Versionen der Methode fetch sollten nur die sein, dass ich die referenz auf den reader als Rückgabewert erhalte, anstatt die Zielvariable als referenzierten Parameter zu übergeben. Dieses Rückgabeverhalten war aber nur meinerseits optional erwünscht, um eine ähnliche Handhabung der für mich gewohnten prepared statements aus PHP zu implementieren. Bearbeitet 23. Juli 2014 von Shadowman Zitieren
SilentDemise Geschrieben 23. Juli 2014 Geschrieben 23. Juli 2014 und warum benutzt du nicht einen fertigen OR Mapper samt Repository Pattern? Zitieren
lbm1305 Geschrieben 23. Juli 2014 Geschrieben 23. Juli 2014 gewohnten prepared statements aus PHP zu implementieren. warum bleibst du dann nicht bei php? wenn es etwas mit der frage zu asp.net zu tun hat, kann man doch sicherlich per REST eine abfrage auf einen php-service machen. dann kannst du dein "gewohntes" umfeld nutzen. ansonsten solltest du dich von dem "gewohnten" trennen. zuerst...die klasse hat zuviele aufgaben. aber egal. möglichkeit a) für jede abfrage ein "command-bbjekt" erstellen, welches ein vordefiniertes typisiertes ergebnis zurück gibt einen action-delegate an fetch übergeben, der dann vom benutzer / entwickler angepasst werden kann. // pseudocode void Fetch(Action<DbDataReader> action) { // Verbindung herstellen // Abfrage ausführen // Ergebnis auswerten DbDataReader reader = null; action(reader); // Verbindung schließen. } .... // Aufruf Customer customer = null; Db.Fetch( reader => { if (reader.HasRows) { customer = new Customer { Id = reader.GetInt32() }; } }); Zitieren
Gooose Geschrieben 23. Juli 2014 Geschrieben 23. Juli 2014 Sicherlich ist es hilfreich, sich die grundlegenden Datenbank-Klassen anzuschauen, um zu schauen, wie es unter .NET läuft. Spätestens wenn du typisiert arbeiten willst, kommst du in die Lage eine Menge Boilerplate Code (CRUD) zu schreiben. Schau dir mal https://code.google.com/p/dapper-dot-net/ an. Du kannst deine Queries typisiert abfeuern und mit .NET Listen arbeiten. Die Bibliothek wurde von Stackoverflow entwickelt, um eine möglichst schlanke Verbindung zur Datenbank zu haben. Gruß, gooose Zitieren
Shadowman Geschrieben 23. Juli 2014 Autor Geschrieben 23. Juli 2014 weil ich ein neuling in .net bin und das noch nicht kannte (direkt mal durchlesen) Zitieren
Gooose Geschrieben 23. Juli 2014 Geschrieben 23. Juli 2014 Relationale Daten auf Klassen abbilden ist erst mal sprachunabhängig. Nimm dir für den Anfang zwei einfache Tabellen, die du joinen musst. (z.B. Rechnung und Rechnungspositionen) und versuche diese sinnvoll abzubilden. So kannst du schneller erkennen, ob dein Ansatz gut funktioniert, oder nicht. Zitieren
Shadowman Geschrieben 24. Juli 2014 Autor Geschrieben 24. Juli 2014 Ich habe die Vorgabe keine externen Frameworks einzusetzen. Das was von Microsoft direkt vorhanden ist kann ich nutzen, sonst leider nichts, deswegen habe ich mir auch die eigene DB Klasse geschrieben. Naja, dieses Thema hat sich ja eh schon erledigt, da ich es einfach so gelassen habe, wie ichs in der alternative schon drin hatte. Jetzt habe ich jedoch ein ganz anderes Problem, was auch wieder daher kommt, dass ich ein absoluter Anfänger bin, was ASP.NET angeht: Ich habe in meiner Datenbank eine Tabelle mit Gruppen, welche ich auf einer aspx Seite ausgeben möchte. Dies habe ich mit einer asp:Table versucht, wo ich aber feststellen musste, dass es in ASP-Elementen nicht möglich ist das Ergebnis meines Querys zeilenweise innerhalb der Seite zu durchlaufen und währenddessen neue Zeilen in die asp:Table Element zu schreiben. Ich habe mir dann etwas zu GridViews angeguckt und auch hier feststellen müssen, dass ich das irgendwie mit der DataSource nicht wirklich hinbekomme. <% oracle db = new oracle(); System.Data.Common.DbDataReader group = null; db.prepare("SELECT * FROM zdvs_groups ORDER BY name ASC"); db.execute(); while(db.fetch(ref group)) { %> <!-- hier soll die Zeile ausgegeben werden --> <% } db.close(); %> Solchen Programmcode kann man laut einigen Quellen nicht innerhalb von Elementen ausführen, welche runat="server" als Parameter haben. Jetzt habe ich versucht das ganze in einer normalen HTML Table darzustellen, bekomme jetzt aber den Fehler "Der Typ- oder Namespacename "global_asax" ist im Namespace "ASP" nicht vorhanden." Bei einer .master Seite hat man die Möglichkeit in einer .cs Datei im Hintergrund zu steuern und Felder zu befüllen. Dies geht aber nicht bei normalen Seiten (zumindest finde ich sowas nicht). Kann mir bitte jemand einen Tipp geben, wie ich die Befüllung aus der View rausnehmen kann und es endlich hinbekomme eine Darstellung der Gruppen zu schaffen? Gruß Shadowman Zitieren
lbm1305 Geschrieben 24. Juli 2014 Geschrieben 24. Juli 2014 Scheinbar hast Du hier eine andere Frage, was einen neuen Thread / ein neues Thema rechtfertigen würde. Grund: Falls ein andere Benutzer das gleiche oder ein ähnliches Problem hat, würde es nicht so schnell finden. Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.