Autor Beitrag
lukll1
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Fr 15.08.14 20:23 
Hallo liebe Community,

und zwar bin ich bei der Programmierung eines Programms auf ein problem gestoßen, und zwar möchte ich die Daten einer Spalte einer Access Datenabank in einem Array speichern, leider funktioniert es aber nicht

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
while (m_Reader.Read() == true)
{
    string ID = (m_Reader[0].ToString());            
    string Fragen= (m_Reader[1].ToString());
    string Antworten = (m_Reader[2].ToString());
}

wie man bei diesem Code erkennt, habe ich die Daten der Datenbank in einer string variable gespeichert, will sie aber in einem string array speichern, da ich die daten einzeln später brauche(also jede zeile brauche ich später extra), leider weiß ich aber nicht wo ich dieses array erstellen soll und wo ich dann die for-schleife programmieren soll.
mfg
lukll

Moderiert von user profile iconTh69: Quote- durch C#-Tags ersetzt
Th69
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Moderator
Beiträge: 4764
Erhaltene Danke: 1052

Win10
C#, C++ (VS 2017/19/22)
BeitragVerfasst: Fr 15.08.14 20:56 
Hallo und :welcome:,

statt einem Array würde ich dir eine List<> vorschlagen, da du bei einem Array ja schon im voraus die Größe wissen mußt.
Und für die Daten einer Zeile empfehle ich dir eine eigene Klasse dafür anzulegen:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
class QuizText
{
  public string ID { get; set; }
  public string Frage { get; set; }
  public string Antwort { get; set; }
}

Jetzt die Benutzung davon:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
var texts = new List<QuizText>();

while (m_Reader.Read()) // das '== true' ist überflüssig
{
    string id = m_Reader[0].ToString();
    string frage = m_Reader[1].ToString();
    string antwort = m_Reader[2].ToString();

    var quizText = new QuizText()
    {
       ID = id,
       Frage = frage,
       Antwort = antwort
    };

    texts.Add(quizText);
}

Nun stehen die Daten in der Variablen texts drin.
Solltest du doch ein Array benötigen, so kannst du dann mittels texts.ToArray() eines erzeugen. Das sollte jedoch meistens nicht notwendig sein, da du mit der List<> dieselben Methoden zur Verfügung hast wie bei einem Array (z.B. den Index-Operator [int]). Die Anzahl kannst du dann aus der Eigenschaft Count lesen.

Solltest du einigen Code davon noch nicht verstehen (ich nehme an, daß du noch Anfänger bist), so kannst du ja danach im Internet suchen bzw. gezielt Fragen hier stellen.

Für diesen Beitrag haben gedankt: lukll1
lukll1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Mo 18.08.14 10:42 
Danke für die ausführliche Antwort, leider kommt bei mir allerdings immer die Fehlermeldung:

"Quiz.Quiz" enthält keine Definition für "id", und dass gleiche nochmal für frage und antwort.

Quiz heißt bei mir das ganze Projekt und Quiz ist auch der Name der Klasse(deshalb: Quiz.Quiz)

edit: Beitrag selbst gelöst(habe vergessen eine neue Klasse zu machen :D )
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mo 18.08.14 11:14 
Zitat:
Quiz heißt bei mir das ganze Projekt und Quiz ist auch der Name der Klasse(deshalb: Quiz.Quiz)


Du solltest Klassen, wenn irgendwie möglich, nicht wie den Namesspace (bzw.Teile des Namesspaces) benennen in dem sich die Klasse befindet. Bei der Auflösung von Bezeichner wirst du sonst oft genug in Probleme laufen weil der Compiler denkt hier ist der Namespace gemeint und nicht die Klasse. Auch wenn es hier nicht das Problem war aber aus genau diesem Grund bekommst du dann auch Fehlermeldungen das bestimmte Bezeichner nicht gefunden werden können die nicht wirklich eindeutig auf das tatsächliche Problem hinweisen.

Für diesen Beitrag haben gedankt: lukll1
lukll1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Di 19.08.14 10:35 
Ja, das ist natürlich richtig, habs schon geändert, wahrscheinlich bin ich eh durcheinandergekommen beim ersten mal wie der Fehler da war.
Da es das erste mal ist, dass ich mit Listen arbeite, hab ich noch ne frage
sind jetzt alle Daten meiner Datenbank in der Variable "texts" gespeichert?
wenn ja, dann ist wieder irgendwo ein Fehler drinnen, denn wenn ich dann eine int variable erstelle und text.Count(also schauen wie viele Werte in texts drinnen ist), und dass dann ausgebe, dann kommt immer nur 1,2,3,4,5,.....,46,47 und nach 47 kommmt (Auflistung).
ich habe aber mehr wie 47 Werte in die Datenbank eingegeben, listbox kann auch nicht schuld sein, da ich sie extra mit scrollen ausgestatte habe(zur Vorsorge).

ausblenden Quelltext
1:
2:
3:
texts.Add(quiz);
int anzahl = texts.Count();
m_lbProbe.Items.Add(anzahl.ToString()); //ich weiß, dass .ToString() am Ende ist nicht wichtig, aber zur Vorsorge


Nur zu Klarheit, eigentlich ist die l-Box völlig sinnlos, habe sie nur zu Überprüfungszwecken gemacht.
Außerdem ist mir ein wenig unklar, wie man z.B. aus der Liste texts nun einen eindeutigen Wert herausfiltern kann, also z.B. will ich nur in der l-Box den Wert der Datenbank in der Spalte 2 und der Zeile 4 haben, und nicht die ganze Spalte.
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Di 19.08.14 11:01 
Zitat:
sind jetzt alle Daten meiner Datenbank in der Variable "texts" gespeichert?


Da wir das verwendete SQL nicht kennen können wir die Frage nicht beantworten. Wenn du ein SQL ohne Einschränkungen (where Klausel) und mit allen benötigten Spalten hast dann wird dir der DataReader auch alle Zeilen liefern.

Zitat:
also z.B. will ich nur in der l-Box den Wert der Datenbank in der Spalte 2 und der Zeile 4 haben, und nicht die ganze Spalte.


Zeile 4, Spalte 2 ist genau 1 Wert dafür brauch man keine Listbox da reicht eine TextBox.

Wenn du eine bestimmte Property der Objekte in der Liste anzeigen willst (hier von Spalte zu sprechen ist ungünstig da du nun eine Liste von Objekten hast die technisch nichts mehr mit deiner Datenbank zu tun hat außer das da zufällig die Daten herkamen) dann setzte die DisplayMember Property nach dem du die Liste als DataSource gesetzt hast (in Winforms in WPF must du äquivalent ein wenig anders vorgehen). Dann wird der Inhalt dieser Property aller gebunden Objekte in der ListBox angezeigt.

ausblenden C#-Quelltext
1:
2:
listBox.DataSource = texts;
listBox.DisplayMember = "Frage";


Wenn du gar nicht alle Datenzeilen anzeigen willst dann stellt sich die Frage warum du nicht gleich dein SQL passend einschränkst (mit einer Where Klausel). Erstmal alles aus der DB zu laden um dann einen Teil wieder wegzuwerfen weil man gar nicht alles braucht ist völlig ineffektiv.

Wenn du in anderem Context alles brauchst aber in dieser speziellen ListBox nur einen Teil brauchst kannst du die Liste vor dem binden z.B. mit einem LINQ Ausdruck nochmal filtern.

ausblenden C#-Quelltext
1:
2:
listBox.DataSource = texts.Where(x=> x.ID < 50 && x.Frage.StartsWith("Wie"));
listBox.DisplayMember = "Frage";

Für diesen Beitrag haben gedankt: lukll1
lukll1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Di 19.08.14 11:46 
erstmals danke für die antwort

ich verwende OLEDB und habe eine while-Schleife:

ausblenden C#-Quelltext
1:
while (m_Reader.Read())					


nur in dieser einen textbox brauch ich einen wert, in einer anderen Textbox wieder einen anderen wert, also brauche ich schon die ganzen daten( in der anderen z.B. Spalte 1 zeile 4) in der nächsten Spalte 2 Zeile 50)...
auch wenn es jetzt nichts mehr mit einer datenbank zu tun hat, nur zur veranschaulichung was ich eigentlich will

ja ich programmiere schon in WindowsForms, deshalb wird es vermutlich anders gehen, wie ich es programmiert habe...
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Di 19.08.14 12:23 
Zitat:
nur in dieser einen textbox brauch ich einen wert, in einer anderen Textbox wieder einen anderen wert


Dann erzähle uns woran du denn Wert erkennst denn du in der TextBox anzeigen willst. Z.B. weil der Datensatz zu der der Wert gehört eine bestimmte ID hat, weil er nach irgendeiner Defintion der aktuelle Datensatz ist u.s.w.

Wenn du eine Property aus dem ~aktuellen~ Datensatz der Liste anzeigen willst dann.

1. Wirf eine BindingSource auf die Form.
2. An dessen DataSource Property wählst du den Typ aus den du an diese BindingSource binden willst (hier wäre das die Klasse die TH69 QuizText genannt hat). Im Editor zur DataSource Property findest du einen Klassennavigator um deine Klasse zu finden.
3. Nun verbindest du die TextBox mit dieser BindingSource. Dazu hat die TextBox im Editor eine (DataBindings) Pseudo Property worunter du wiederum die Text Property findest. Dort wählst du die BindingSource aus und die tatsächliche Property des gebunden Objekts die verwendet werden soll, z.B. Frage.
4. Zur Laufzeit sobald du die Daten geladen hast kannst du die Liste der DataSource Property der BindingSource zuweisen. Ab dann werden die Daten automatisch mit allen gebunden Controls synchronisiert udn angezeigt.
5. Zum Navigieren durch die Daten hat dann die BindingSource entsprechende Methoden bzw. Properties (MoveFirst, MoveNext, MovePrevious, Position, Current etc.)

Für diesen Beitrag haben gedankt: lukll1
lukll1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Di 19.08.14 12:35 
ja genau, die zeile würde ich an der id erkennen;
bitte nehme es mir nicht böse, aber ich meine es leider anders, tut mir leid.
Ich stelle hier mal die Datenbank her:

ausblenden Quelltext
1:
2:
3:
4:
5:
ID  Frage                            Antwort
1   Wer ist aktueller CL-Sieger?      Real Madrid
2   Wer ist aktueller EL-Sieger?      Fc Sevilla
3   Wer ist....                       ...
...


diese Daten habe ich jetzt alle in texts drinnen, soweit ich dass verstanden habe

dann habe ich eine textbox, wo eine dieser Fragen angezeigt werden soll(mit random)

also z.B. Random wählt 2 aus, dann soll kommen "Wer ist aktueller EL-Sieger". Random habe ich schon gemacht und integriert, ich weiß nur nicht wie ich diesen einen Datensatz"Wer ist aktueller EL-Sieger" in der Textbox ausgeben kann von der Datenbank(also jetzt halt von der variable texts)
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Di 19.08.14 12:49 
Dann würde ich mir per Linq die Klasse aus der Liste holen.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
int id = 5// die gewürfelte ID
var texts = new List<QuizText>(); // die noch zu füllende Liste

var question = texts.FirstOrDefault(x=> x.ID == id);
if (question != null// wenn ein Datensatz gefunden wurde
{
   textBoxMitFrage.Text = question.Frage;
   textBoxMitAntwort.Text = question.Antwort;
}


Wenn du garantieren kannst das jede gewürfelte ID auch existiert kannst du First anstatt FirstOrDefault benutzen und dir die folgende if Abfrage sparen.

Für diesen Beitrag haben gedankt: lukll1
lukll1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Di 19.08.14 14:39 
danke, ja dass mit der id kann ich garantieren.

was oder für was steht dieses: (x=> x.ID==id)
und was im speziellen ist x, eine variable, weil ich habe x vorher nie definiert, trotzdem funktioniert es
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Di 19.08.14 15:15 
Das ist ein Parameter für den Lambdaausdruck.
Den Lambdaausdruck kannst du dir auch wie eine Methode vorstellen wobei x dann der Name eines Methodenparameters wäre. Was für ein Typ X ist wird automatisch aus der Methodensignatur von
FirstOrDefault ermittelt die selber in Bezug zum generischen Parameter der Liste steht. Drum ist klar das x ein QuizText ist.


Das
ausblenden C#-Quelltext
1:
var question = texts.FirstOrDefault(x=> x.ID == id);  // Lambda					

ließe sich auch so
ausblenden C#-Quelltext
1:
var question = texts.FirstOrDefault(delegate(QuizText x) { return x.ID == id; });  // anonyme Methode					

bzw. so schreiben
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
var question = names.FirstOrDefault(myCompareMethod);  // normale Methode

private static bool myCompareMethod(QuizText x)
{
    return x.ID == id;
}

Für diesen Beitrag haben gedankt: lukll1
lukll1 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Di 19.08.14 15:55 
ahh, ok, danke für die Info!!!! :zustimm: