Zum Inhalt springen
  • 0

c# InvalidCastException


Frage

Geschrieben

Moin moin ich wieder^^

Ich habe ein Programm das Daten in eine Datenbank schreibt, aber sobald ich die Tabelle in der ich die Datenbank veranschauliche erneuer funktioniert es nicht mehr und ich bekomme einige Exceptions.

Code:

using System.Windows.Forms;
using System.IO;
using System.Text.RegularExpressions;
using MySql.Data.MySqlClient;
using System.Data;
using System;

namespace Message_Admin
{
    public partial class Form1 : Form
    {
        //allgemein
        MySqlConnection connection;
        MySqlDataAdapter adapter;
        string command = "";
        MySqlCommand sqlcommand;

        //ini-Inhalt
        string iniText;
        string iniServer;
        string iniDatabase;
        string iniUser;
        string iniPassword;
        string iniPort;
        string iniTable;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                ReadIniFile();

                //SQL Zeug
                string connectionString = "SERVER=" + iniServer + ";" +
                    "DATABASE=" + iniDatabase + ";" +
                    "UID=" + iniUser + ";" +
                    "PASSWORD=" + iniPassword + ";" +
                    "Port=" + iniPort + ";";
                string command = "SELECT * FROM " + iniTable + ";";
                connection = new MySqlConnection(connectionString);
                connection.Open();

                adapter = new MySqlDataAdapter(command, connection);
                DataSet ds = new DataSet();
                adapter.Fill(ds);

                dataGridView1.DataSource = ds.Tables[0];

                //add CheckBox Column
                DataGridViewCheckBoxColumn chk = new DataGridViewCheckBoxColumn();
                dataGridView1.Columns.Add(chk);
                chk.HeaderText = "Choose";
                chk.Name = "chk";
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        public void ReadIniFile()
        {
            try
            {
                //ini lesen
                iniText = File.ReadAllText("settings.ini");

                //Werte auslesen
                Regex regServer = new Regex("(?<=Server\\=).+");
                Regex regDatabase = new Regex("(?<=Database\\=).+");
                Regex regUID = new Regex("(?<=UID\\=).+");
                Regex regPassword = new Regex("(?<=Password\\=).+");
                Regex regPort = new Regex("(?<=Port\\=).+");
                Regex regMainTable = new Regex("(?<=MainTable\\=).+");

                Match matchServer = regServer.Match(iniText);
                Match matchDatabase = regDatabase.Match(iniText);
                Match matchUID = regUID.Match(iniText);
                Match matchPassword = regPassword.Match(iniText);
                Match matchPort = regPort.Match(iniText);
                Match matchMainTable = regMainTable.Match(iniText);

                iniServer = Convert.ToString(matchServer);
                iniDatabase = Convert.ToString(matchDatabase);
                iniUser = Convert.ToString(matchUID);
                iniPassword = Convert.ToString(matchPassword);
                iniPort = Convert.ToString(matchPort);
                iniTable = Convert.ToString(matchMainTable);
            }
            catch
            {
                MessageBox.Show("Initialisierung der ini-Datei fehlgeschlagen");
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            sqlcommand = new MySqlCommand(command, connection);
            string textbox = richTextBox1.Text;

            foreach (DataGridViewRow row in dataGridView1.Rows)
            {
                try
                {
                    if (Convert.ToBoolean(row.Cells[5].Value) == true)
                    {
                        sqlcommand.CommandText = "update " + iniTable + " set message = '" + textbox + "' where id = " + row.Cells[0].Value + ";";
                        sqlcommand.ExecuteNonQuery();                      
                    }
                    else if (row.Cells[5].Value == null)
                    {

                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
            richTextBox1.Clear();
        }
    }
}

Kurz erklärt: Das Programm ließt ein paar Daten aus einer ini-Datei um sich zur mysql-db zu verbinden. Mit Button 1 wird die Tabelle der Datenbank in das DataGridView eingelesen und ich habe auch noch eine weitere Reihe (row[5]) hinzugefügt die check-Boxen enthält. Soweit funktioniert es auch ohne Probleme.

Wenn ich jetzt aber Button2 ausgeführt habe, dann Button1 klicke um das DataGrid zu aktualisieren und erneut Button2 ausführe bekomme ich eine Exception hier:

if (Convert.ToBoolean(row.Cells[5].Value) == true)

System.InvalidCastException "Ein Objekt kann nicht von DBnull in andere Typen umgewandelt werden"

Dann folgen noch einige andere SQL-Exceptions die wohl einfach nur daraus resultieren.

Ich weiß nicht auf welche Variable ich achten muss oder wie man die Checkboxen die gecheckt sind noch afragen könnte außer es in boolean umzuwandeln (das hatte ich auf Stack Overflow gefunden)

Kann das jemand nachvollziehen oder mir einen Hinweis geben was ich da falsch mache?

Empfohlene Beiträge

  • 0
Geschrieben

Ich habe meinen Fehler gefunden, der durch die Feste größe des Fensters nicht aufgefallen ist. Jedesmal wenn ich Button1 drücke setzt er eine Spalte mit CheckBoxen rechts ran anstatt zu "aktualisieren" wie ich es eigentlich wollte.

dataGridView1.Columns.Clear();

Im Gegensatz zu den 100 Vorschlägen im internet Rows.Clear() zu benutzen (funktioniert null komma null) funktioniert es jetzt mit dem kleinen Zusatz.

 

vor einer Stunde schrieb Whiz-zarD:

Stell dir mal vor, du willst deine Anwendung, die du mit WinForms gebastelt hast, später in eine Webentwicklung umwandeln möchtest. Mit deiner jetzigen Vorgehensweise musst du die Anwendung komplett neu entwickeln, weil die Logik, die die Anwendung steuert, in den WinForms-Komponenten steckt. Du kannst die Logik also nicht weiterverwenden.

Das sagt mir leider auch wenig, noch nie gemacht, noch nie mit zu tun gehabt. Außer stumpfes Code kopieren weiß ich absolut nicht was gemeint ist. Ich weiß´nicht wie ich ein Stück Code in einem späteren Projekt verwenden kann ohne es even wie gehabt stumpf zu kopieren (falls das damit gemeint ist).

  • 1
Geschrieben

Hallo Tician,

ich würde mir an deiner Stelle ein Fachbuch besorgen, z.B. Head First C# (das dürfte auf deine Personenbeschreibung am besten passen). 

Dir fehlen einfach zu viele Grundlagen, um dir in einem Forum effizient zu helfen. Das ist keine Faulheit der Benutzer hier, sondern eher die Frage "womit soll man bei Dir anfangen?".

Von der Lektüre eines Fachbuchs wirst Du auf jeden Fall deutlich mehr profitieren, als wenn dir hier einige Poster Brocken hinschmeißen, die du dann doch gedanklich nicht richtig verarbeiten kannst.

Programmieren lernen ist ein langer Prozess, das geht nicht von heute auf Morgen.

Weiterhin viel Erfolg.

  • 1
Geschrieben
vor 1 Stunde schrieb Tician:

Das mit dem Weiterbilden ist schwierig du willst das ich ein Pferd zeichne ohne je eines gesehen zu haben, sprich ich soll meinen Code in etwas umwandeln das ich noch nie gesehen habe und unter dem ich mir gerade nichts vorstellen kann und gar nicht weiß wo ich ansetzen soll.

Und genau das ist es ja, was ich meine: Es fehlen zu viele Grundlagen.
Ich könnte jetzt anfangen, dass du dieses und jenes in eine Klasse packen kannst oder die Code-Teile in Methoden auslagern solltest aber du wirst es nicht verstehen. Dir ist nicht mal klar, warum man die Geschäftslogik von der Benutzeroberfläche trennen sollte. Man müsste dir also erst mal erklären, was Methoden und Klassen sind, was Vererbung oder Geheimhaltungsprinzip bedeutet, etc. Dann kommt man von einem zum anderen und das hat dann schon eher den Charakter eines Nachhilfeunterrichts. Für sowas ist ein Forum auch eine äußerst schlechte Kommunikationsplattform. 

Es ist nicht böse gemeint aber ich denke, du nimmst dir zu viel auf einmal vor. Man sollte sich zwar Ziele setzen aber die Ziele sollten auch erreichbar sein und bei dir sind die Ziele noch Meilenweit entfernt und gerade Softwareentwicklung entwickelt sich sehr schnell in Richtung Frust. Vor allem wenn das Projekt immer Größer wird und Anpassungen gemacht werden müssen. Es hat schon seine Gründe, warum die Entwicklung von Software oft sehr lange dauert und sehr kostspielig ist. Sowas macht man nicht einfach nebenbei und auch nicht alleine. Schon gar nicht bei Software, die über mehrere Jahre stabil laufen sollen auch wenn sie sehr trivial erscheint. 

vor 1 Stunde schrieb Fauch:

ich würde mir an deiner Stelle ein Fachbuch besorgen, z.B. Head First C# (das dürfte auf deine Personenbeschreibung am besten passen). 

Die Schrödinger-Reihe (Schrödinger programmiert C#) vom Rheinwerk-Verlag soll auch nicht schlecht sein.

  • 0
Geschrieben (bearbeitet)

Das Problem ist, dass du versuchst, einen null-Wert (aus der Datenbank) nach boolean zu konvertieren. Das geht einfach schief. Der simple Weg ist, vor dem Convert zu prüfen, ob der Wert DBNull ist, also:

var cellValue = row.Cells[5].Value;
if(cellValue != DBNull.Value && Convert.ToBoolean(cellValue))
{
	// ...
}

So wird die Umwandlung nach boolean nur vorgenommen, wenn du auch tatsächlich einen Wert da stehen hast. Gegebenenfalls kannst du die if-Abfrage auch noch um ein "cellValue != null" ergänzen; kommt ganz drauf an, wie du die Daten da reinlegst.

Auf mittlere / lange Sicht könntest du dir überlegen, wie du verhinderst, dass solche inkompatiblen Daten überhaupt da landen können. Du könntest entweder dafür sorgen, dass die Default-Werte immer in die Datenbank geschrieben werden, oder du kümmerst dich beim Auslesen darum, dass sinnvolle Standardwerte gesetzt werden.

Kleiner Hinweis noch, der nichts mit diesem konkreten Problem zu tun hat, der mir aber immer ein wenig aufstößt: Wenn du einen Ausdruck zu bool auswerten kannst, kannst du dir das "== true" sparen. Macht die Sache (m.M.n.) übersichtlicher.

Bearbeitet von arlegermi
  • 0
Geschrieben

 

Erst mal, wenn du schon Kommentare wie 

//SQL Zeug
//add CheckBox Column
//ini lesen

etc.

schreibst, dann lager den Code doch in separate Methoden aus. Das macht die Methoden kleiner und übersichtlicher und mit Hilfe geeigneter Methodennamen ist der Code auch sprechender.

Zweitens, öffnest du eine Datenbank-Verbindung aber du schließt sie nie wirklich. Mit Button1 öffnest du sie aber du schließt sie nie. Für gewöhnlich öffnet man eine Datenbank-Verbindung und wenn man fertig ist, wird sie wieder geschlossen. Man hält sie nicht einfach offen.

Drittens, du schreibst Fachlogik in die UI. Das sollte man vermeiden.

Zum eigentlichen Problem:
Dein 

row.Cells[5].Value

ist vom Typ DBNull und kann daher nicht in ein Boolean gewandelt werden.
Überprüfe doch mal, was von der Datenbank überhaupt zurückkommt und welcher Wert im GridView steht.

 

  • 0
Geschrieben (bearbeitet)

Ihr habt glaube ich beide etwas missverstanden.

Die Datenbank die ausgelesen wird geht nur bis Cell[4], während Cell[5] die Reihe ist die ich manuell mit CheckBoxen eingefügt habe. Das DataGrid ist NICHT mit der Datenbank verknüpft, es ließt sie nur aus und setzt eine checkBox-Spalte mit dran die nichts mit der Datenbank zu tun hat und die ich nur benutze um Reihen auszuwählen in denen ich etwas verändern möchte.

//add CheckBox Column
                DataGridViewCheckBoxColumn chk = new DataGridViewCheckBoxColumn();
                dataGridView1.Columns.Add(chk);
                chk.HeaderText = "Choose";
                chk.Name = "chk";

@Whiz-zarD

Ich bin kein Programmierer, ich habe (außer in der Schule) nie einen richtigen Code zu einem Programm gesehen und hier im Betrieb bin ich auch die einzige die mehr als nur batch-skripte schreibt.

Die Programme zur Optimierung von Prozessen schreibe ich alle weil ich gerne programmiere, deswegen bin ich auch für Vorschläge offen, deswegen Danke für deine Tipps!

Alles was ich mehr als 1 mal brauch packe ich normalerweise auch in eine Methode, aber meine Programme sind alle so klein das es für mich einfacher ist das von oben nach unten zu lesen.

vor einer Stunde schrieb Whiz-zarD:

du schreibst Fachlogik in die UI

Keine Ahnung was damit gemeint ist, sorry.

Ich versuche mich mal an arlegermi's Vorschlag zur Problemlösung

Bearbeitet von Tician
  • 0
Geschrieben
vor 20 Minuten schrieb Tician:

Ihr habt glaube ich beide etwas missverstanden.

Die Datenbank die ausgelesen wird geht nur bis Cell[4], während Cell[5] die Reihe ist die ich manuell mit CheckBoxen eingefügt habe. Das DataGrid ist NICHT mit der Datenbank verknüpft, es ließt sie nur aus und setzt eine checkBox-Spalte mit dran die nichts mit der Datenbank zu tun hat und die ich nur benutze um Reihen auszuwählen in denen ich etwas verändern möchte.


//add CheckBox Column
                DataGridViewCheckBoxColumn chk = new DataGridViewCheckBoxColumn();
                dataGridView1.Columns.Add(chk);
                chk.HeaderText = "Choose";
                chk.Name = "chk";

 

Du legst die Spalte nur an, aber sie wird nicht mit Daten befüllt.

Ich kenne mich auch nicht mit der DataGridViewCheckBoxColumn aus, aber offenbar handelt es sich hier eine Spalte, die ein Mapping besitzt, da man über die Property TrueValue bzw. FalseValue steuern kann, wann true oder false zurückgeliefert werden soll:

https://msdn.microsoft.com/en-us/library/system.windows.forms.datagridviewcheckboxcolumn(v=vs.110).aspx

vor 39 Minuten schrieb Tician:

Keine Ahnung was damit gemeint ist, sorry.

Stell dir mal vor, du willst deine Anwendung, die du mit WinForms gebastelt hast, später in eine Webentwicklung umwandeln möchtest. Mit deiner jetzigen Vorgehensweise musst du die Anwendung komplett neu entwickeln, weil die Logik, die die Anwendung steuert, in den WinForms-Komponenten steckt. Du kannst die Logik also nicht weiterverwenden.

  • 0
Geschrieben

Das gesuchte Schlüsselbegriff ist Schichtenarchitektur

Zitat

Ich weiß´nicht wie ich ein Stück Code in einem späteren Projekt verwenden kann ohne es even wie gehabt stumpf zu kopieren

Der Trick: Den Code in eine separate DLL zu packen und mehrere Projekte können darauf verweisen und verwenden. (Projekttyp: Klassenbibliothek bzw. ClassLibrary)

 

  • 0
Geschrieben

Oke, das muss ich irgendwann mal machen, dann kommt auch schon das nächste Thema: Wenn ich separate Klassen und Methoden habe wie rufe ich das auf? Im Prinzip weiß ich wie ich eine Methode einer anderen Klasse aufrufe und auch wie ich Parameter mit übergebe, aber jetzt sitze ich vor dem hier:

namespace BlockTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //??? NativeMethods.BlockInput(true) ???
        }
    }

    public partial class NativeMethods
    {
        [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "BlockInput")]
        [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
        public static extern bool BlockInput([System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)] bool fBlockIt);

        public static void BlockInput(TimeSpan span)
        {
            try
            {
                NativeMethods.BlockInput(true);
                Thread.Sleep(span);
            }
            finally
            {
                NativeMethods.BlockInput(false);
            }
        }
    }
}

Das soll später noch mit in das andere Programm rein und einen Benutzer daran hinder Eingaben zu machen während wir am System arbeiten, aber ich weiß nicht wie ich das (jetzt zum testen mit dem Button) benutzen kann.

Ich habe BlockInput() mit einem bool-Wert und hoffe das so aufrufen zu können aber wo kann ich dann die Zeitspanne festlegen?

  • 0
Geschrieben

Ist das wichtig? Ich arbeite in einem Logistik-Betrieb, jeden Tag muss jemand von unserer Abteilung (IT und Projektmanagement) drüben in unserem Logistik-Gebäude anrufen und dort muss dann jemand rumrennen und an 10 Plätzen bescheid geben das nicht mehr gearbeitet werden darf weil wir dann einen Abschluss von wasauchimmer (UPS, DHL, irgendwie sowas ich hab den Überblick noch nicht ganz) machen.

Ich mache also eine Software die aus Client-Software und "Admin"-Software besteht (ich habe es nicht Server genannt weil ich keine Ahnung von Netzwerkprogrammierung habe und alles über eine Datenbank schleife).

Im Admin-Programm (das was ihr jetzt gesehen habt) wird in einer DataGrid die DB-Tabelle gelistet. Mit Haken kann man anwählen welche Clients man auswählen möchte um einen Text in die Datenbank zu setzen - und einen 2. Haken um einen bool-wert in die Datenbank zu setzen der das blockieren der Tastatur und Maus für eine gewissen Zeit ankündigt.

Das Client-Programm hat ein unsichtbares Fenster, beim ersten Ausführen schreibt sich der Computer mit PC-Name und Benutzername in die Datenbank. Anschließend wird im 10-sekunden takt die Datenbank überprüft, wenn dann ein Text drin steht wird dieser als Vordergrund-MessageBox angezeigt und bei Bestätigung wieder auf "nix" gesetzt. Das funktioniert alles, aber der Block-Befehl ist eben noch gewünscht und fehlt.

Das ganze läuft Domänen-intern, kein Virus und auch sonst kein Unsinn falls du das gedacht hast.

Klar, es würde bestimmt etwas im internet geben und unsere interne Fernwartungssoftware hat auch einen Button um Tastatur und Maus zu blockieren, aber eben nur an einem PC und ich programmiere gerne und dann würde der Lerneffekt ausfallen :)

  • 0
Geschrieben

Client (jaja ich weiß der sieht auch grausam aus)

namespace Message_Client
{
    public partial class Form1 : Form
    {
        //allgemein
        string hostname;
        string user;
        string names;
        string text;
        MySqlConnection connection;
        MySqlCommand sqlcommand;
        MySqlDataReader reader;

        //ini-Inhalt
        string iniText;
        string iniServer;
        string iniDatabase;
        string iniUser;
        string iniPassword;
        string iniPort;
        string iniTable;

        public Form1()
        {
            InitializeComponent();

            try
            {
                ReadIniFile();

                this.FormBorderStyle = FormBorderStyle.None;
                this.ShowInTaskbar = false;
                this.Load += new EventHandler(Form1_Load);

                System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
                timer.Tick += Timer_Tick;
                timer.Interval = 10000;
                timer.Start();
                hostname = Environment.MachineName;
                user = Environment.UserName;
                Microsoft.Win32.SystemEvents.SessionEnding += SystemEvents_SessionEnding;

                //SQL Zeug
                string connectionString = "SERVER="+iniServer+";" +
                    "DATABASE=" + iniDatabase + ";" +
                    "UID=" + iniUser  +";" +
                    "PASSWORD=" + iniPassword +";" +
                    "Port=" + iniPort +";";
                string command = "SELECT hostname FROM " + iniTable + ";";
                connection = new MySqlConnection(connectionString);
                sqlcommand = new MySqlCommand(command, connection);

                //open connection and execute command
                connection.Open();
                reader = sqlcommand.ExecuteReader();
                while (reader.Read())
                {
                    var name = reader["hostname"];
                    names += " "+name;
                }
                reader.Close();

                //find own hostname with Regex           
                Regex reg1 = new Regex(hostname);
                Match match1 = reg1.Match(names);

                //create hostname in DB if not found
                if (!match1.Success)
                {
                    sqlcommand.CommandText = "insert into " + iniTable +" (hostname, message, user, block) values ('" + hostname+"', '0','"+user+"', '0');";
                    sqlcommand.ExecuteNonQuery();
                }

                sqlcommand.CommandText = "update " + iniTable + " set status=1 where hostname='" + hostname + "';";
                sqlcommand.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }           
        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            try
            {
                sqlcommand.CommandText = "select message from " + iniTable + " where hostname='" + hostname + "';";
                reader = sqlcommand.ExecuteReader();
                while (reader.Read())
                {
                    var vartext = reader["message"];
                    text = Convert.ToString(vartext);
                }
                reader.Close();

                if (text != "0")
                {
                    MessageBox.Show(text, "IT Abteilung sagt:", MessageBoxButtons.OK, MessageBoxIcon.Warning,MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
                    sqlcommand.CommandText = "update " + iniTable + " set message='0' where hostname='" + hostname + "';";
                    sqlcommand.ExecuteNonQuery();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.Size = new Size(0, 0);
        }

        public void ReadIniFile()
        {
            try
            {
                //ini lesen
                iniText = File.ReadAllText("settings.ini");

                //Werte auslesen
                Regex regServer = new Regex("(?<=Server\\=).+");
                Regex regDatabase = new Regex("(?<=Database\\=).+");
                Regex regUID = new Regex("(?<=UID\\=).+");
                Regex regPassword = new Regex("(?<=Password\\=).+");
                Regex regPort = new Regex("(?<=Port\\=).+");
                Regex regMainTable = new Regex("(?<=MainTable\\=).+");

                Match matchServer = regServer.Match(iniText);
                Match matchDatabase = regDatabase.Match(iniText);
                Match matchUID = regUID.Match(iniText);
                Match matchPassword = regPassword.Match(iniText);
                Match matchPort = regPort.Match(iniText);
                Match matchMainTable = regMainTable.Match(iniText);

                iniServer = Convert.ToString(matchServer);
                iniDatabase = Convert.ToString(matchDatabase);
                iniUser = Convert.ToString(matchUID);
                iniPassword = Convert.ToString(matchPassword);
                iniPort = Convert.ToString(matchPort);
                iniTable = Convert.ToString(matchMainTable);
            }
            catch
            {
                MessageBox.Show("Initialisierung der ini-Datei fehlgeschlagen");
            }
        }


        //when program is closed
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            sqlcommand.CommandText = "update " + iniTable + " set status=0 where hostname='" + hostname+"';";
            sqlcommand.ExecuteNonQuery();
            connection.Close();
        }
        private void SystemEvents_SessionEnding(object sender, Microsoft.Win32.SessionEndingEventArgs e)
        {
            sqlcommand.CommandText = "update " + iniTable + " set status=0 where hostname='" + hostname + "';";
            sqlcommand.ExecuteNonQuery();
            connection.Close();
        }

        
    }

    public partial class NativeMethods
    {
        [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint="BlockInput")]
        [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
        public static extern bool BlockInput([System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)] bool fBlockIt);

        public static void BlockInput(TimeSpan span)
        {
            try
            {
                NativeMethods.BlockInput(true);
                Thread.Sleep(span);
            }
            finally
            {
                NativeMethods.BlockInput(false);
            }
        }
    }
}

Achja das FormClosing und SessionEnding funktionieren auch nicht, da muss ich mir noch was überlegen wie ich das testen kann, schätzungsweise mal als Admin ausführen.

  • 0
Geschrieben (bearbeitet)

Ich finde es, ehrlich gesagt, schon ein hartes Stück, dass eine Person, die von Programmierung und offenbar auch von UX (User Experience) keine Ahnung hat und dann eine Software für den produktiven Einsatz entwickelt. Auch wenn du dich dafür interessierst, heißt es nicht, dass es funktioniert, was du da tust. Dein gesamter Code ist sehr fehleranfällig und auch unwartbar. Wenn jemand anders die Software weiterentwickeln soll, steht er dort vor einer Wartungshölle, die dazu führt, dass die Person die Software neuschreiben muss. Auch wenn du diese Software weiterentwickeln willst, wird der Aufwand immer weiter steigen, da immer mehr Fehler und Seiteneffekte hinzukommen.

Mit Aufrufen aus der Win32-API begibst du dich auf sehr dünnen Eis. Da muss man schon wissen, was man da tut. Die Win32-API ist sog. unmanaged Code. Als Anfänger solltest du lieber die Finger von lassen. Wenn du also schon die Anwendung sperren willst (was ich nicht für schlau halte), dann öffne eine zweite Form mit einem Hinweis-Text. Die darunterliegende Form kann man dann nicht in den Fokus holen.

vor 56 Minuten schrieb Tician:

Im Admin-Programm (das was ihr jetzt gesehen habt) wird in einer DataGrid die DB-Tabelle gelistet. Mit Haken kann man anwählen welche Clients man auswählen möchte um einen Text in die Datenbank zu setzen - und einen 2. Haken um einen bool-wert in die Datenbank zu setzen der das blockieren der Tastatur und Maus für eine gewissen Zeit ankündigt.

Also muss das Admin-Tool mit den Clients kommunizieren. Also fungiert das Admin-Tool als Server und die Clients müssen sich am Server registrieren. Irgendwie muss das Admin-Tool ja mit den Clients kommunizieren oder sollen die Clients tatsächlich alle 10 Sekunden eine Abfrage an die Datenbank starten, die den derzeitigen Status überprüft? Also hast du eine Verzögerung von maximal 10 Sekunden, wo der Anwender weiterhin Eingaben tätigen kann und glaub mir, das wird passieren.

Ich würde dir echt empfehlen, es sein zu lassen, was du da tust. Offenbar nimmst du ja auch nicht mal Ratschläge an oder versuchst, dich weiterzubilden. Stattdessen versuchst du per Copy&Paste eine Client-Server-Software zu bauen. Das kann nur in die Hose gehen. Nichts für ungut, aber ich sehe derzeit keine Chance dir weiterzuhelfen, da schon das nötige Grundwissen fehlt und davon rede ich nicht mal von Client-Server-Architektur, sondern von allgemeinen Dingen.

Bearbeitet von Whiz-zarD
  • 0
Geschrieben

Ich hatte doch extra gesagt es gibt keine direkte Kommunikation zwischen Client und "Server" weswegen ich es auch nicht Server genannt habe. Das Admin-Tool ist dazu da um Dinge auf die Datenbank zu schieben und zu verändern, während der Client die Datenbank abruft und je nach Inhalt reagiert. Die 10 Sekunden lassen sich bei Bedarf ja ändern, es gibt sowieso noch ein paar andere Wünsche an Änderungen an denen ich noch arbeiten muss.

Das mit dem Weiterbilden ist schwierig du willst das ich ein Pferd zeichne ohne je eines gesehen zu haben, sprich ich soll meinen Code in etwas umwandeln das ich noch nie gesehen habe und unter dem ich mir gerade nichts vorstellen kann und gar nicht weiß wo ich ansetzen soll.

Das nächste ist das ich weder heute noch gestern groß weitergekommen bin, die Client UND die "Server"-Seite standen Code-mäßig auch schon am Montag fest bevor mir hier Tipps gegeben wurden, ich programmiere nicht 100% meiner Arbeitszeit.

Produktiv im EInsatz ist nur eines meiner Programme, das jetzige und 2 andere sind in Arbeit. Ich bin Azubi, mir macht programmieren Spaß, es ist nicht geplant irgendwann jemanden einzustellen der programmieren kann geschweige denn das irgendjemand meine winzigen Programme auch nur mit einem Auge anschaut.

Es ist schade aber verständlich für mich das du mir da nicht helfen willst, ich bin anfänger, mir fehlt Grundwissen, ich habe niemanden den ich fragen kann, noch NIE einen anderen Code gesehen und über ein Forum ist es massiv zeitaufwendig etwas zu erklären, während man den Wissensstand des anderen nicht kennt, gleichzeitig (das ist meine persönliche Meinung) bist du nicht gut darin etwas Anfänger-freundlich zu erklären, allerdings versuchst du mir in jedem Thread zu helfen, das rechne ich dir wirklich hoch an. Gleichzeitig bin ich aber ein Typ der etwas nur sehr langsam versteht und auch nur dann wenn es quasi kindergerecht und anschaulich erklärt wird.

Es gibt andere Leute hier, andere Foren und morgen schmeiße ich mich auch mal auf einen Programmier-Stammtisch, irgendwo hoffe ich hilfe zu finden.

 

  • 0
Geschrieben

Das ist doch mal eine Ansage, mein Betrieb bestellt mir Head First C# 3rd edition :)

Mein englisch ist ziemlich gut (ich mach auch das freiwillige Englisch-Zertifikat dieses Schuljahr) von daher kein Problem^^

Danke! Mal schauen wie gut ich damit zurecht komme, ich habe mich jetzt voll auf deine Einschätzung und dem verlassen was ich so auf ein paar Blicke gesehen habe :)

  • 0
Geschrieben (bearbeitet)

Habe ich verstanden, aber in den Grundlagen ist nie von sowas die Rede gewesen und dann heißt es "such dir ein Projekt, so lernt man am Besten" und ich finde ich habe schon einiges gelernt nur wende ich es falsch bzw nicht programmier-freundlich an?

Im Vergleich zur Schule wo wir jetzt zum ersten mal eine neue Datei als Klasse erstellt haben und einen Button machen der im viereck im Fenster umher springt sobald man drauf klickt. Da habe ich verstanden das ich die Werkzeuge mit etwas (in dem Beispiel den Timer) verknüpfen kann und dann im Hauptcode soviele Buttons wie ich will aufrufen kann, aber ich bekomme das nicht auf das übertragen was ich hier mache, vorallem nicht nur nach diesem einen Beispiel.

Mal schauen wie bald ich meinen Code dann überarbeiten kann

 

Edit: Huch die Posts sind nach oben gewandert, jetzt sieht das aus als würde ich Selbstgespräche führen >.<

Bearbeitet von Tician
  • 0
Geschrieben
vor 9 Minuten schrieb Tician:

Im Vergleich zur Schule wo wir jetzt zum ersten mal eine neue Datei als Klasse erstellt haben und einen Button machen der im viereck im Fenster umher springt sobald man drauf klickt. Da habe ich verstanden das ich die Werkzeuge mit etwas (in dem Beispiel den Timer) verknüpfen kann und dann im Hauptcode soviele Buttons wie ich will aufrufen kann, aber ich bekomme das nicht auf das übertragen was ich hier mache, vorallem nicht nur nach diesem einen Beispiel.

Das ist leider so ein Problem. Oft lernt man nur triviale Dinge und diese werden dann wegen der Einfachheit nicht richtig erklärt bzw. nicht genug durchleuchtet. Es werden dann Risiken und Probleme ausgeklammert und gar nicht behandelt, weil das einen Anfänger verwirrt. Ich finde auch, ein Anfänger sollte nicht mit einer Benutzeroberfläche anfangen, sondern mit einem Kommandozeilen-Tool, um überhaupt erst mal ein Gefühl für die Sprache zu entwickeln. Eine Kommandozeile ist auch nicht so komplex wie eine Benutzeroberfläche. Microsoft hat es zwar nett gemeint, mit dem WinForms-Designer aber leider hat sich herausgestellt, dass die einfache Herangehensweise (Button in die Form ziehen, Doppelklick auf den Button und ausprogrammieren) zu vielen Problemen führt. Nicht umsonst haben sich Schlaue Köpfe überlegt, wie man die Entwicklung von Oberflächen von der Geschäftlogik entkoppelt und Dinge wie MVC (Model-View-Controller), MVP (Model-View-Presenter) oder MVVM (Model-View-ViewModel) entworfen. Ich sage ja nicht, dass ein Anfänger sich nun streng daran halten sollte, denn diese Techniken sind nicht unbedingt leicht zu verstehen aber ich finde, es ist schon wichtig, dass ein Anfänger die Teilaufgaben in seinem Projekt erkennt und die Teilaufgaben in Klassen und Methoden gliedert. 

Buttons rumspringen lassen, halte ich auch nicht für zielführend. Ein Anfänger sollte schon sinnvollere Aufgaben lösen. In meinem Studium haben wir u.a. anfangen die Fibonacci-Reihenfolge zu berechnen oder ein Sudoku-Löser zu entwickeln. 

  • 0
Geschrieben

Ich kann nur die Aussagen von den anderen untermalen. Fang lieber erstmal mit etwas kleineren an.

Zitat

Das mit dem Weiterbilden ist schwierig du willst das ich ein Pferd zeichne ohne je eines gesehen zu haben, sprich ich soll meinen Code in etwas umwandeln das ich noch nie gesehen habe und unter dem ich mir gerade nichts vorstellen kann und gar nicht weiß wo ich ansetzen soll.

Genau da liegt doch das Problem und du beschreibst es schon selber. Du hast noch nie strukturierten, wartbaren und generischen Code gesehen, versuchst aber in ein Projekt zu schreiben, welches sich in den Workflow, bzw. in das Tagesgeschäft einmischt. Entschuldige, aber das ist bei weitem keine gute Idee.

 

  • 0
Geschrieben

Was wäre denn dann etwas "kleineres"? In der Schule haben wir jetzt eine Klasse erstellt in der wir einen Button und einen Timer "verbunden haben", sodass man diese Buttons einfügen kann und die dann im viereck springen sobald man drauf klickt.

Dann noch ein "Sitzplatz-Reservierungs-Programm" bei dem 100 Buttons sich gründ/rot färben wenn man drauf klickt.

Damit habe ich mal verstanden wie ich eine andere Klasse schreibe und benutze und das ich für ein SpaceInvader keine 1000 Zeilen Code brauche :D

Aber in diesen Beispielen befindet sich der komplette Code auch nur in einer Klasse und die wird nur als Objekt aufgerufen, ich weiß nicht ob sich das groß von dem unterscheidet was ich hier fabriziert habe.

  • 0
Geschrieben (bearbeitet)

Natürlich kann man die Welt auch nur mit einer Klasse retten aber das ist nicht Sinn und Zweck der Objektorientierung.
Bei der Objektorientierung kann man eigentlich jedes simple Problem in mehrere Klassen aufteilen. Wenn man es dann dogmatisch betrachtet, kann man es so weit führen, dass in jeder Klasse nur noch eine Methode steckt.

Wenn du das Single-Responsibility-Prinzip verstanden und dir auch verinnerlicht hast, bekommst du auch ein Gespür dafür, wie Klassen und Methoden gestaltet werden müssen. Ein Beispiel: Wir wollen eine Klasse schreiben, die eine E-Mail verschicken soll. Das Interface sieht im ersten naiven Schritt so aus:

public interface IEMailSender 
{
	public string From { get; set; }
	public string To { get; set;
	public string Title { get; set; }
	public string Content { get; set; }
	public void Send();
}

Wir sehen hier, dass From und To vom Typ String sind. Da kann alles mögliche drinnen stehen. Wir müssen also prüfen, ob es valide E-Mail-Adressen sind. Der naive Gedanke wäre nun, eine private Methode in der Implementierung des Interfaces zu basteln:

public class EMailSender : IEMailSender
{
	public string From { get; set; }
	public string To { get; set;
	public string Title { get; set; }
	public string Content { get; set; }

	public void Send()
	{
		if(this.IsVaildEMailAddress(this.From) && this.IsVaildEMailAddress(this.To))
		{
			// TODO: Versende E-Mail
		}
	}

	private bool IsVaildEMailAddress(string potentialEMailAddress)
	{
		// TODO: Überprüfung auf korrekte Adresse
	}
}

Aber ist die Validierung der E-Mail-Adresse wirklich die Aufgabe des E-Mail-Versenders? Nein.
Muss der Versender den Titel und den Inhalt explizit wissen? Nein.
Der E-Mail-Versender soll nur die E-Mail versenden. Mehr nicht.

Also sollte man anfangen, die einzelnen Bestandteile zu zerlegen. Was brauchen wir denn alles für den E-Mail-Versand? Wir brauchen eine E-Mail und ein Versender. Die E-Mail ist noch mal unterteilt in eine Sender- und Empfänger-Adresse, Titel und Inhalt. Also:

public interface IEMailSender
{
    void Send(EMail eMail);
}
public class EMailSender : IEMailSender
{
    public void Send(EMail email)
    {
        if(email == null)
            throw new NullReferenceException();
            
        // TODO: Versende E-Mail
    }
}
public class EMail
{
    public EMailAddress From { get; set; }
    public EMailAddesss To { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
}
public class EMailAddress
{
    public string Address { get; }

    public EMailAddress(string address)
    {
        if(!this.IsValidFormat(address))
            throw new FormatException();

        this.Address = address;
    }

    private bool IsValidFormat(string potentialEMailAddress)
    {
        // TODO: Überprüfung auf korrekte Adresse
    }
}

Der E-Mail-Sender muss dann nur noch prüfen, ob er auch eine E-Mail zum Versenden bekommen hat. Die Validierung, ob die E-Mail-Adressen korrekt sind, passiert dann schon beim Setzen der E-Mail-Adresse.

Der Aufruf erfolgt dann so:

EMail email = new EMail
{
    From = new EMailAddress("foo@bar.de"),
    To = new EMailAddress("bar@foo.de"),
    Title = "Hallo Welt",
    Content = "Ist das Wetter nicht schön?"
}

IEMailSender sender = new EMailSender();
sender.Send(email);

Mit Dependency Injection könnte man dann noch den EMailSender in die Klasse reinreichen, wo er verwendet wird. Dann würde man innerhalb der Klasse nur noch gegen das Interface arbeiten und wäre von der konkreten Implementierung unabhängig.

Wie du siehst, haben wir bei diesem Beispiel schon drei Klassen und ein Interface geschrieben.
Ich kenne jetzt eure Beispiele in der Schule nicht aber wenn ich schon sowas lese, wie "Sitzplatz-Reservierungs-Programm", dann kann ich mir nicht vorstellen, dass man euch wirklich die Objektorientierung richtig erklärt, wenn ihr dafür nur eine Klasse geschrieben habt. Alleine wenn ihr schon eine GUI (WinForms oder WPF) verwendet habt, dann fallen mir schon spontan drei Klassen ein, die man dafür bräuchte, um das Problem gekapselt abzubilden. Das Stichwort wäre hier MVC (Model-View-Controller) bzw. MVP (Model-View-Presenter).

Bearbeitet von Whiz-zarD
  • 0
Geschrieben
vor 8 Stunden schrieb Tician:

Was wäre denn dann etwas "kleineres"?

Gerade das ist ja oft nicht sinnvoll möglich. Du weißt ja auch nicht was du machen könntest. Am Ende istdie Anforderung halt das was die Anforderung ist.
Was du machen kannst ist dich bestmöglich vorzubereiten. Dazu empfehle ich dir, dass du das Projekt tatsächlich nochmal ein wenig zurückstellst und davor einmal Code Complete von Steve McConnell durcharbeitest. Da werden die meisten Grundlagen ordentlich eingeführt und von da aus kannst du dann weiter gehen und dich der echten Anforderung widmen.

  • 0
Geschrieben

Jo, Code Complete hat ja auch nur etwa 750 Seiten + Anhänge. 

Manche machen hier echt seltsame Vorschläge. Die TE ist FiSi und hat von Programmieren nicht wahnsinnig viel Ahnung. Da mit Code Complete, Clean Coding und Design Patterns anzukommen (zum Einstieg!) ist Quark.

Gerade CC wirft schon zu Anfang des ersten Kapitels mit UML und Fachausdrücken nur so um sich. 

  • 0
Geschrieben

Man sollte zwar Anfängern nicht gleich solche Schinken zum Fraß vorwerfen aber ich finde, man sollte schon so früh wie möglich, sich mit solchen Themen beschäftigen. Wir haben bei uns gerade einen Schülerpraktikanten, den wir eine Aufgabe zum Lernen gegeben haben, da unsere Anwendung für einen Anfänger zu komplex und wohl auch zu langweilig sein wird. Ja, er schreibt Spaghetticode. Für den Anfang kann er das auch ruhig. Dennoch haben wir bemerkt, dass er sich ein bisschen schwer tut, durch sein Code zu navigieren und sein Code zu debuggen, weil er selber nicht so ganz weiß, was sein Code macht und wo eine Aktion ausgeführt wird. Wir haben ihn ein paar Tipps gegeben, wie er die Klassen und Methoden gestalten kann und haben ihn geholfen, sein Code zu strukturieren. Danach fand er sich im Code auch wesentlich besser zurecht.

Das Problem kenne ich auch aus eigener Erfahrung, als ich zur Schulzeit nur hobbymäßig programmierte. Bei jedem Projekt verlor ich schnell die Lust, weil ich irgendwann nicht mehr durch meinen Code durchgestiegen bin und auch sehr fehleranfällig war, weil ich einfach nicht die Strategien kannte, wie man seinen Code strukturiert.

vor einer Stunde schrieb afo:

Wie soll man denn deiner Meinung nach Einsteigen? Den Unterschied zwischen If-Schleifen und For-While-Unterscheidungen lernt man durch Tutorial oder Spracheinführungsbücher innerhalb weniger Tage. Aber wie soll man deiner Meinung nach lernen wie man ein Stück Software baut wenn man eben keinen Ausbilder im Betrieb hat der einen (evtl. an Hand einer bestehenden Software) Stück für Stück daran heranführen kann?

Ich hoffe, dass deine "If-Schleifen" und "For-While-Unterscheidungen" irgendwie lustig gemeint sein sollte. Ansonsten:

http://www.if-schleife.de/ ...

 

  • 0
Geschrieben
vor 18 Minuten schrieb Whiz-zarD:

Man sollte zwar Anfängern nicht gleich solche Schinken zum Fraß vorwerfen aber ich finde, man sollte schon so früh wie möglich, sich mit solchen Themen beschäftigen. Wir haben bei uns gerade einen Schülerpraktikanten, den wir eine Aufgabe zum Lernen gegeben haben, da unsere Anwendung für einen Anfänger zu komplex und wohl auch zu langweilig sein wird. Ja, er schreibt Spaghetticode. Für den Anfang kann er das auch ruhig. Dennoch haben wir bemerkt, dass er sich ein bisschen schwer tut, durch sein Code zu navigieren und sein Code zu debuggen, weil er selber nicht so ganz weiß, was sein Code macht und wo eine Aktion ausgeführt wird. Wir haben ihn ein paar Tipps gegeben, wie er die Klassen und Methoden gestalten kann und haben ihn geholfen, sein Code zu strukturieren. Danach fand er sich im Code auch wesentlich besser zurecht.

Das Problem kenne ich auch aus eigener Erfahrung, als ich zur Schulzeit nur hobbymäßig programmierte. Bei jedem Projekt verlor ich schnell die Lust, weil ich irgendwann nicht mehr durch meinen Code durchgestiegen bin und auch sehr fehleranfällig war, weil ich einfach nicht die Strategien kannte, wie man seinen Code strukturiert.

Ich hoffe, dass deine "If-Schleifen" und "For-While-Unterscheidungen" irgendwie lustig gemeint sein sollte. Ansonsten:

http://www.if-schleife.de/ ...

 

Sehe ich mehr oder weniger auch so, wir müssen uns aber vor Augen halten, dass der TE auf sich allein gestellt ist. Was man in der Berufsschule lernt, ist schon bei den FIAEs nicht besonders viel (und vor allem meist nicht besonders fundiert). Als FISI wird's da eher noch magerer aussehen.

Auch sowas wie Clean Coding kann bereits zu Anfang sinnvoll sein - allerdings nur, wenn da auch ein Ausbilder dahintersteht, der weiß was er tut! Die ersten zwei Kapitel, die z.B. Namensgebung und Aufteilung in Funktionen abhandeln, kann man auch schon im ersten Lehrjahr abhandeln.

Dem TE aber so einen Wälzer vorzusetzen und dann zu sagen: "Arbeite das doch mal durch" ist wahrscheinlich sogar kontraproduktiv.

  • 0
Geschrieben (bearbeitet)
vor 3 Minuten schrieb afo:

Hast du das Buch gelesen, oder zumindest das Inhaltsverzeichnis und das Vorwort überflogen?

Ich habe das Buch durchgelesen und lese auch gern immer wieder nach, um Kenntnisse aufzufrischen.

Im Wesentlichen schließe ich mich aber der Meinung hier an:

http://softwareengineering.stackexchange.com/questions/13778/when-one-should-read-code-complete

 

 

 

 

Bearbeitet von Fauch

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
Diese Frage beantworten...

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