Zum Inhalt springen

Analogie zu prepared statements aus PHP erstellen


Shadowman

Empfohlene Beiträge

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

Link zu diesem Kommentar
Auf anderen Seiten teilen

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)

Link zu diesem Kommentar
Auf anderen Seiten teilen

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).

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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)

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.
Link zu diesem Kommentar
Auf anderen Seiten teilen

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);

}

Link zu diesem Kommentar
Auf anderen Seiten teilen

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 :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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 von Shadowman
Link zu diesem Kommentar
Auf anderen Seiten teilen

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

B) 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()

                        };

                    }

                });


Link zu diesem Kommentar
Auf anderen Seiten teilen

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

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Link zu diesem Kommentar
Auf anderen Seiten teilen

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

Link zu diesem Kommentar
Auf anderen Seiten teilen

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.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung wiederherstellen

  Nur 75 Emojis sind erlaubt.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

Fachinformatiker.de, 2024 by SE Internet Services

fidelogo_small.png

Schicke uns eine Nachricht!

Fachinformatiker.de ist die größte IT-Community
rund um Ausbildung, Job, Weiterbildung für IT-Fachkräfte.

Fachinformatiker.de App

Download on the App Store
Get it on Google Play

Kontakt

Hier werben?
Oder sende eine E-Mail an

Social media u. feeds

Jobboard für Fachinformatiker und IT-Fachkräfte

×
×
  • Neu erstellen...