C# Datenbanken - Abfrage über 2 Tabellen vereinfachen

Neue Frage »

Auf diesen Beitrag antworten »
InformaTiger C# Datenbanken - Abfrage über 2 Tabellen vereinfachen

Hallo,
ich bin bei folgendem Problem:
in meiner Datenbank habe ich 2 Tabellen (tbl_jobs, tbl_subjobs) die in einer 1:n Beziehung miteinander verknüpft sind. Aus denen würde ich gerne auslesen welcher Job welche Unterjobs hat. Dies habe ich so umständlich es nur ging, folgendermaßen umgesetzt:

code:
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[] res = db.ReadDatabase("SELECT MAX(ID) FROM tbl_jobs;");
                int x = 30, y = 30, del = 25, job = 0;
                int.TryParse(res[0], out job);

[...]
               
 for (int i = 1; i < job + 1; i++)
                {
                    res = db.ReadDatabase("SELECT tbl_jobs.name FROM tbl_jobs WHERE ID = " + i + ";");
                    pnlView.Controls.Add(new Label() { Text = res[0].ToUpper() + ":", Location = new Point(x, y), ForeColor = border, AutoSize = true });

                    res = db.ReadDatabase("SELECT COUNT(job) FROM tbl_subjobs WHERE job = " + i + ";");
                    int subjobs = 0, index = 0;
                    int.TryParse(res[0], out subjobs);

                    res = db.ReadDatabase("SELECT ID FROM tbl_subjobs WHERE job = " + i + " ORDER BY ID ASC;");
                    int.TryParse(res[0], out index);

                    for (int j = index; j < index + subjobs; j++)
                    {
                        res = db.ReadDatabase("SELECT description, done FROM tbl_subjobs WHERE ID = " + j + ";");
                        pnlView.Controls.Add(new CheckBox() { Text = res[0], Checked = bool.Parse(res[1]), Location = new Point(x + del, y + del), ForeColor = border, AutoSize = true });
                        y += del * 2;
                    }
                }


Meine Frage: Wie geht das wesentlich einfacher?

Danke schon im Vorraus smile

Mfg
InformaTiger
 
Auf diesen Beitrag antworten »
ed209

1. Wieso hast Du es so umständlich es nur ging umgesetzt?

2. Woran siehst Du daß es wesentlich einfacher geht?
Auf diesen Beitrag antworten »
InformaTiger

Hallo ed209,

nun das mit "so umständlich wie möglich", ist reine Gefühlssache von mir. Wenn ich mir den Codeblock ansehe komme ich schon allein durch seine Größe bzw. seinen Umfang zum Schluss, dass es einfacher gehen muss. Nur sehe ich eben meistens nicht wie... unglücklich

Mfg
InformaTiger
Auf diesen Beitrag antworten »
InformaTiger

Es ergab sich mittlerweile ein weiteres Problem: Ich habe in meinem Hauptpanel wo dynamisch Inhalt erzeugt wird die Eigenschaft AutoScroll auf true gesetzt um nach unten scrollen zu können falls der Platz eng wird. Es funktioniert auch nur habe ich ein Problem mit meinem Rahmen der wie folgt erzeugt wird:

code:
1:
2:
3:
4:
5:
6:
        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            g.DrawRectangle(new Pen(new SolidBrush(border), 2), new Rectangle(1, 1, this.Width - 2, this.Height - 2));
            base.OnPaint(e);
        }


Es werden mehrere Rahmenlinen zu viel gezeichnet (siehe Anhang). Es sollte jedoch nur ein Rahmen gezeichnet werden. Hat jemand eine Ahnung warum das so ist?

Mit freundlichen Grüßen
InformaTiger
 
Auf diesen Beitrag antworten »
eulerscheZahl

Von Datenbanken habe ich keine Ahnung, aber so umständlich wirkt das auf mich nicht.
Zum Problem mit den Rechtecken kann man so nichts sagen, da fehlen einfach Informationen. Helfen würde ein Code, der möglichst kurz ist und auch diesen Fehler produziert (der ist ja unabhängig vor der Datenbank, also z.B. die jobs/subjobs direkt in ein Array schreiben als aus der Datenbank ziehen, dann muss ein potentieller Helfer nicht noch die Datenbank zum Laufen bringen, um das Programm nachzuvollziehen).

Zu deiner OnPaint Methode:
du erstellst ein Graphics Objekt, entfernst es aber anschließend nicht aus dem Speicher. Das sind zwar jetzt "nur" ein paar Byte, aber wenn du Methode oft aufgerufen wird, kann das trotzdem einProblem werden.
Entweder rufst du, wenn du es nicht mehr benötigst, g.Dispose() auf um den Speicher freizugeben, oder du nimmst gleich using(Graphics g = e.Graphics) { ... }, dadurch wird dann implizit auch Dispose aufgerufen.
Auf diesen Beitrag antworten »
InformaTiger

Hallo eulersche Zahl,

das Graphics Objekt habe ich aus dem Grund nicht entfernt da ich wenn ich mich recht erinnere dadurch einen Fehler bekam. Getestet: ich habe mich geirrt. Es funkioniert ohne Fehler, danke für den Tipp.

Standardmäßig wird das Panel so gezeichnet:

code:
1:
2:
3:
4:
5:
6:
        private void pnlView_Paint(object sender, PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            g.DrawRectangle(new Pen(new SolidBrush(border), 2), new Rectangle(1, 1, pnlView.Width - 2, pnlView.Height - 2));
            g.Dispose();
        }


Wenn man auf den Button klickt um sich die Aufgaben anzeigen zu lassen werden dynamisch die entsprechenden Steuerelemente erzeugt (wie in der Schleife bereits gezeigt). Ich denke der Fehler liegt bei der oben gezeigten Methode da ich sonst nicht wirklich etwas mit Graphics mache. Im Anhang: Code der mit Graphics in meinem Programm zu tun hat.
Auf diesen Beitrag antworten »
ed209

Zitat:
Original von InformaTiger
Hallo ed209,

nun das mit "so umständlich wie möglich", ist reine Gefühlssache von mir. Wenn ich mir den Codeblock ansehe komme ich schon allein durch seine Größe bzw. seinen Umfang zum Schluss, dass es einfacher gehen muss. Nur sehe ich eben meistens nicht wie... unglücklich

Mfg
InformaTiger


In der Tat müsste das ganze mit einem einzigen Query lösbar sein.

1. Du willst eine Liste mit allen Jobs haben, aber Du fragst jeden einzeln ab. SQL ist durchaus in der Lage dir alle Jobs als eine Liste zurückzugeben.

Ich kenne die Klassen die Du für SQL Abfragen benutzt nicht, aber ich bin mir ziemlich sicher daß die das unterstützen sollten.

Dafür musst du den folgende Query einfacher machen:
code:
1:
 SELECT tbl_jobs.name FROM tbl_jobs WHERE ID = " + i + "; 


Dasselbe kannst Du dann mit dem Query machen der dir die Jobs zurückgibt.

Das macht dein Programm nicht nur simpler und (vermutlich) effizienter, sondern auch richtiger:

Was ist wenn du einen Job 2 hast mit den Subjobs 40, 41 und 43?


2. Wenn Du das alles erledigt hast sollten nur noch zwei verschiedene Queries in deinem Programm stehen. Einer in für Jobs außerhalb und einer für Subjobs in der Schleife.
Wenn Du soweit bist ist das Programm schon viel besser und du könntest es auch dabei belassen.

Aber wenn Du den Feinschliff noch machen willst, dann kannst Du die beiden Queries auch noch vereinen. Dafür empfehle ich dir über den Befehl JOIN nachzulesen in deiner liebsten SQL-Quelle.

Gruß,
ED
Auf diesen Beitrag antworten »
InformaTiger

In der Tat wäre es relativ einfach die zwei Queries zu verschmelzen:
code:
1:
2:
SELECT tbl_jobs.name, tbl_subjobs.description, tbl_subjobs.done FROM tbl_jobs
INNER JOIN tbl_subjobs ON tbl_jobs.ID = tbl_subjobs.job;

Das Problem liegt dabei dann nur bei der Ausgabe da ich Logik Schwierigkeiten habe, wie ich jedes erste Element des Arrays als "name" hinein schreibe, jedes zweite als "description" und jedes dritte als "done". Um es anders zu formulieren: Für jeden Job muss ein Label generiert werden. Solange es in diesem Job Subjobs gibt müssen jeweils Checkboxen erzeugt werden.

Das Geheimniss liegt im Modulo nur habe ich eben wenig Ahnung wie.

Zitat:
Original von ed209
Was ist wenn du einen Job 2 hast mit den Subjobs 40, 41 und 43?

Was du damit meintest ist mir unklar!

Mfg
InformaTiger
 
Neue Frage »
Antworten »


Verwandte Themen

Die Beliebtesten »
Die Größten »
Die Neuesten »