Danke für die Hinweise. Ich habe deine (sheitman) Vorschläge eingearbeitet.
Bei der Gelegenheit habe ich die Anzeige der Anwendung etwas erweitert, sodass man Ostersonntag und Buß- und Bettag für ein "beliebiges" Jahr direkt prüfen kann. Damit kommen solche Fehler hoffentlich nicht mehr vor.
[offtopic]Ich wundere mich, dass ich den Buß- und Bettag nicht kontrolliert hatte. Ebenso wundere ich mich über die Convert-Anweisung beim Ostersonntag; solche Konstruktionen hatte ich eigentlich schon vor neun Jahren als schlechten Stil abgelehnt. Besser spät als nie korrigieren![/offtopic]
Die Version von Feiertage.zip habe ich entsprechend ergänzt.
Wichtiger Hinweis: Die vorstehende Berechnung genügt nicht: Zwei Ausnahmeregeln wurden bei den obigen Lösungen nicht in die Gaußsche Formel eingearbeitet. Der Ordnung halber folgt hier die berichtigte Berechnung:
/// <summary>
/// Errechnet das Datum des Ostersonntags aus dem übergebenen Jahr
/// </summary>
/// <param name="jahr">Das Jahr YYYY als integer-Wert</param>
/// <returns>Das errechnete Datum des Ostersonntags in dem angegebenen Jahr</returns>
private DateTime GetOstersonntag(int jahr)
{
int x = jahr; // das Jahr
int k; // die Säkularzahl
int m; // die säkulare Mondschaltung
int s; // die säkulare Sonnenschaltung
int a; // der Mondparameter
int d; // der Keim für den ersten Vollmond im Frühling
int r; // die kalendarische Korrekturgröße
int og; // die Ostergrenze
int sz; // der ersten Sonntag im März
int oe; // die Entfernung des Ostersonntags von der Ostergrenze
int os; // das Datum des Ostersonntags als Märzdatum (32.März = 1.April)
int OsterTag;
int OsterMonat;
k = x / 100;
m = 15 + (3 * k + 3) / 4 - (8 * k + 13) / 25;
s = 2 - (3 * k + 3) / 4;
a = x % 19;
d = (19 * a + m) % 30;
r = (d + a / 11) / 29;
og = 21 + d - r;
sz = 7 - (x + x / 4 + s) % 7;
oe = 7 - (og - sz) % 7;
os = og + oe;
OsterMonat = 2 + (int)(os + 30) / 31;
OsterTag = os - 31 * ((int)OsterMonat / 4);
return Convert.ToDateTime(OsterTag.ToString() + "." + OsterMonat + "." + jahr);
}
[offtopic]Auf diesen Fehler wurde ich kürzlich durch eine Änderung bei der Wikibooks-Algorithmensammlung aufmerksam gemacht.[/offtopic]
Die hier stehende Version von Feiertage.zip habe ich entsprechend ergänzt.
eigenartig, dass so einfache dinge nicht "ordentlich" funktionieren,...
Ich bin gerade auch über das Problem gestolpert und habe hier die Lösung (KeyPress-Code von rechner) gefunden. Ich war ebenfalls überrascht, aber .NET arbeitet "as designed", siehe TextBoxBase.ShortcutsEnabled:
Zitat
The TextBox control does not support the CTRL+A shortcut key when the Multiline property value is true.
Es ist schön, dass über myCSharp eine einfache Lösung zu finden ist. Jürgen
Was ist ein XSD Befehl? xsd ist XML-Schema, also die Festlegung wie ein XML-Dokument aussehen soll. Was du mit "aus DLL generieren" meinst versteh ich grad nicht.
Es gibt beides: Zum einen ist xsd eine Extension für ein xml-Dokument, das die Struktur eines DataSet beschreibt. Zum anderen gibt es xsd.exe, das daraus eine Designer.cs-Datei erstellt. Das ist aber "nur" ein typisiertes DataSet, kein TableAdapter.
Den TableAdapter selbst lehne ich ab: Bei diesem Datenmonster sind viel zu viele Abläufe versteckt, sodass man nicht weiß, was eigentlich passiert. Deshalb kann ich nichts dazu sagen, wie man auch xsc und xss bekommt. Ich befürchte, dass dies in der fertigen DLL nicht mehr enthalten ist, weil es um die Steuerung des Designers geht und nicht um die Laufzeit.
Die bisherigen Erklärungen sind völlig korrekt. Aber dein Code hat mit der Fehlermeldung wenig zu tun; deshalb können die Erklärungen nicht vollständig sein. Es fehlt der Hinweis darauf, woher thisRow eigentlich kommt (jedenfalls kann ich nichts erkennen). Jürgen
Kann es sein das die Update Methode von MySqlDataAdapter einen benutzt, und diesen aus irgenteinen Grund nicht mehr schließt.
Es ist denkbar, weil der DbDataAdapter auch den Erfolg des Speichern prüft. Das könntest du über den .NET Reflector kontrollieren.
Zitat
Desweiteren stimmt das überhaupt so mit dem UpdateCommand?
Nein. Wenn du den UPDATE-Befehl manuell zuweist, muss er genau dem SQL-Befehl entsprechen, also mit SET, den Spalten und den Werten (natürlich als Parameter). Einfacher ist es, einen SELECT zuzuweisen; dann kann der DbDataAdapter sich die Speichern-Befehle in der Regel selbst erstellen (sofern der SELECT die Voraussetzungen erfüllt: kein JOIN, mit PrimaryKey).
Zitat
Auserdem ist mir grad noch aufgefallen das es nur bei Tabellen geschieht wo es auch Änderungen gab.
Natürlich, so arbeitet die Update-Methode des DbDataAdapter, wie in :rtfm: beschrieben wird.
Alles zusammen ist das ein Grund mehr, sowohl DbConnection als auch DbDataAdapter in einem using-Block zu kapseln.
was die Ungenauigkeiten angeht, hab ich das nun so verstanden das es bei solchen Berechnungen besser wäre direkt auf decimal zurückzugreifen?
Nein, eher nicht. Beim BMI kommt es (anders als in der Buchhaltung) nicht auf Genauigkeit an; da passen double-Werte. Du musst nur bei den Vergleichen aufpassen, also dich nicht auf exakte Gleichheit verlassen.
wie das Formatieren des SELECT helfen soll, ist mir schleierhaft. Aber es gibt andere Möglichkeiten: Unter connectionstrings wird OleDb statt Odbc empfohlen. Die dort ebenfalls genannte Schema.ini bietet auch Möglichkeiten, wie Felder formatiert werden können.
Außerdem findet man z.B. unter codeproject fertige CsvReader.
ich glaube nicht dass ein Grid das macht, wenn man einen Reader als DataSource einhängt.
Auch dafür hilft ein Blick in :rtfm: DataGridView.DataSource ist zwar als object deklariert, aber aus den Beschreibungen geht hervor, dass der Typ zu einem der folgenden Interfaces passen muss:
The IList interface, including one-dimensional arrays.
The IListSource interface, such as the DataTable and DataSet classes.
The IBindingList interface, such as the BindingList<(Of <(T>)>) class.
The IBindingListView interface, such as the BindingSource class.
Damit und mit dem Hinweis von chilic ist klar, dass der DbDataReader das nicht leisten kann: Der ist etwas, was "abläuft", als Liste wird etwas Fertiges, Statisches benötigt.
@Doltsche Lösung 1: Es wird eine geeignete Liste erzeugt und beim Auslesen des DbDataReaders manuell mit Inhalt gefüllt. Lösung 2: Mit einer Methode wird das Ergebnis des DbDataReaders direkt in eine DataTable gepackt. Es gibt eine solche Methode, ich vergesse aber immer wieder, wie sie heißt. Also die Suche bemühen... Lösung 3: Erstelle eine DataTable und benutze zum Abholen der Daten DbDataAdapter.Fill(thisTable).
Nur hierbei ist das Problem das in der Collection keine Spalte ID vorhanden ist, denn die stammt ursprünglich aus einem DataGridView.
Wenn das wirklich so ist, dann hast du womöglich einen Grundsatz von .NET nicht verstanden: Trenne Daten und Anzeige!
Wenn du Daten per Code bearbeiten willst, dann solltest du immer eine Datenmenge bearbeiten. Beim DataGridView steckt oft (nicht immer, nicht unbedingt) eine DataTable dahinter. Bearbeite diese, dann verschwinden eine Menge Probleme im Nirwana. Lediglich das Umwandeln von DataGridViewRow (nämlich aus den SelectedRows) nach DataRow sieht wegen mehrfacher Konvertierungen etwas umständlicher aus.
Wenn du in einer Datenzeile eine ID brauchst, dann benutze sie doch. Ob sie im DGV angezeigt wird oder nicht, ist (siehe oben) nebensächlich.
... oder noch besser eine Lösung ganz ohne Treiber.
Da dBase eine relativ einfache Datenstruktur benutzt, könnte man das Einlesen sogar selbst programmieren. Voraussetzung ist natürlich, dass es sich nicht pro Vorgang um Millionen Daten handelt und sie nur gelesen werden müssen.
In deinem Fall dürfte es sich um eine einzige Tabelle handeln (oder um einige wenige), sodass die Struktur selbst nicht analysiert werden muss, sondern feststeht. Aus der dbf-Version ergibt sich die Größe des Dateikopfs, der überlesen werden kann; aus der Tabellenstruktur ergibt sich die Größe eines Datensatzes, der blockweise eingelesen, aufgeteilt und in einzelnen Datenfeldern (DataTable oder List<T>) registriert werden kann.
Ich kann mir sehr gut vorstellen, dass eine solche Lösung unter CodeProject schon zu finden ist.
Wenn du vorher behauptet hast, dass du "keine connectionStrings o.ä." benutzt, dann hat Jack dir offensichtlich etwas Neues erzählt.
Zitat
Das man mit Delete() und Remove() arbeiten kann ist bekannt,
Auch dazu gibt es etwas Neues: Remove in der DataTable hilft überhaupt nichts; solche Datensätze sind sofort in der betreffenden DataTable verschwunden und können vom TableAdapter nicht in der Datenbank entfernt werden. Das klappt nur mit Delete, aber nicht mit Remove.
Zitat
dachte es gibt nur eine geschicktere Lösung um alles auf einmal zu löschen.
Dann verwende das, was du kennst:
Zitat
In SQL gibt es den Befehl TRUNCATE TABLE aber wie kann man diesen Befehl in meinem Fall übergeben?
Die Antwort lautet natürlich:
Zitat von mg.net
die Möglichkeit über SqlCommand.
Dafür ist SqlCommand vorgesehen: Jeder SQL-Befehl kann damit ausgeführt werden.
Bitte etwas weniger Überheblichkeit und etwas mehr Nachdenken über Antworten! Jürgen
du willst eine bestimmte Situation analysieren. Unter Windows geht das mit Ereignissen; das DGV hat ein Ereignis, das eintritt, wenn die (bisher aktive) Zeile verlassen wird. Dieses Ereignis hat (wie viele andere DGV-Ereignisse) in speziellen EventArgs den Verweis auf die (bisher aktuelle) Zeile und Spalte. Du musst also CurrentCell passend festlegen.
Achtung: Wenn du nicht aufpasst, wird dadurch erneut dieses Ereignis ausgelöst. Vielleicht musst du noch einen Zwischenwert speichern und die neue Zelle erst in einem späteren Ereignis festlegen.
wenn du dich mit OOP beschäftigen willst (und das ist immer wichtig und richtig, erst recht mit .NET), dann musst du auch "richtig denken": Eine Klasse soll ein Objekt der Wirklichkeit abbilden. Also solltest du zuerst darüber nachdenken, welchen Teil der Wirklichkeit du behandeln willst: eine Datei oder eine Textzeile oder nicht eher einen bestimmten Sachverhalt oder...
Dann geht es weiter: Welche Eigenschaften haben diese Objekte? Welche Aktionen können diese Objekte vornehmen, welche Aktionen macht ein Benutzer damit?
Auf diese Weise kommst du sozusagen zwangsläufig zu einer Klassenstruktur.
Ich kann keinen Sinn darin erkennen, eine Textdatei als eigene Klasse zu definieren. Es wird schon (je nach Programmsituation) von .NET als Stream, als Folge von Zeilen oder als String-Array zur Verfügung gestellt. Damit kann alles erledigt werden, was denkbar ist. Eine eigene Klasse ist doch nur dann sinnvoll, wenn der Inhalt der Textdatei einen besonderen Teil der Wirklichkeit beschreibt.
Naja aber Hans Wurst in der Datenbank, ist doch aber auch Hans Wurst in der Ausgabe? :)
Aber für diverse Unicode-Zeichen, die hier gar nicht dargestellt werden können, gilt das nicht. Schon "ÄÖÜß" werden je nach CharSet unterschiedlich gespeichert (mit 1 oder 2 Bytes). Aber MaxLength ist natürlich trotzdem der richtige Weg. Jürgen
So pauschal lässt sich das nicht beantworten. Es hängt von Art, Umfang und Zusammenhang der Daten ab. 1,5 GB nur mit Zahlen? Gibt es keine Zusammenhänge der Werte? Wie soll das in DB-Tabellen abgebildet werden? Dann kann die DB zwar schnellere Zugriffe liefern, aber es kann kaum Speicherplatz eingespart werden.
Außerdem kommt so eine Frage immer wieder vor. Benutze die Forumssuche mit vielen verschiedenen Suchbegriffen (Datenbank, Textdatei, Einstellungen, speichern usw.).
Gruß Jürgen
PS. Die deutsche Rechtschreibung kennt Groß- und Kleinschreibung. Dies ist keine Quälerei für Schüler, sondern dient dem Leser zum besseren Verständnis.
Zur Frage der RGB-Anteile: Es gibt die Methode Color.ToArgb. Laut :rtfm: sollten die Bestandteile durch mehrfache Division und Modulo-Operation mit 256 zu erhalten sein.
Außerdem musst du dich mit der Gültigkeit von Variablen befassen. Wenn du in Main einen Spieler deklarierst und erzeugst, weiß keine andere Stelle des Programms etwas davon. Wo und wie wird eigentlich das Formular erzeugt und aufgerufen?
Zum Löschen aller Datensätze gibt es (im Prinzip, also im SQL-Standard) den TRUNCATE-Befehl. Aber auch dann kann die Existenz von ForeignKeys das Löschen ausbremsen.
Gruß Jürgen
@spacenet (nächster Beitrag)
Das hatte ich befürchtet; vorsichtshalber hatte ich "im Prinzip" geschrieben.