Laden...

SQLite mit mehreren Tabellen - Datenbank ohne Redundanzen

Erstellt von dominik.jonczyk vor 7 Jahren Letzter Beitrag vor 7 Jahren 9.337 Views
dominik.jonczyk Themenstarter:in
13 Beiträge seit 2017
vor 7 Jahren
SQLite mit mehreren Tabellen - Datenbank ohne Redundanzen

verwendetes Datenbanksystem: SQLite

In der Anlage habe ich ein Datenbankschema angehängt.
Das Programm ist soweit lauffähig mit Visual Studio C#, jedoch habe ich alles in einer Tabelle, also nicht nach dem Datenbankschema.

string sql = "create table if not exists Personen" +
                                          "(ID integer primary key autoincrement, " +
                                          "Anrede varchar(50), " +
                                          "Vorname varchar(50), " +
                                          "Nachname varchar(50), " +
                                          "Strasse varchar(50), " +
                                          "PLZ varchar(5), " +
                                          "Ort varchar(50), " +
                                          "Email varchar(50), " +
                                          "Telefon varchar(20)" +
                                          ");";

Ziel ist es, die Anwendung so zu gestalten, dass keine Redundanzen in der Datenbank entstehen. Also nach unten abgebildeten Datenbankschema.

Es ist mir schon klar, dass noch drei weitere Tabellen erstellt werden müssen und obige entsprechend geändert werden muss:

string sql = "create table if not exists Personen" +
                                          "(ID integer primary key autoincrement, " +
                                          "Vorname varchar(50), " +
                                          "Nachname varchar(50), " +
                                          "Strasse varchar(50), " +
                                          "Hausnummer varchar(4), " +
                                          "Telefon varchar(20)" +
                                          "PLZ_id integer, " +
                                          "Anrede_id integer, " +
                                          "Titel_id integer, " +
                                          "FOREIGN KEY(PLZ_id) REFERENCES PLZ(PLZ_id), " +
                                          "FOREIGN KEY(Anrede_id) REFERENCES Anrede(Anrede_id), " +
                                          "FOREIGN KEY(Titel_id) REFERENCES Titel(Titel_id), " +
                                          ");";

sqlite_cmd.ExecuteNonQuery();

string sql = "create table if not exists PLZ" +
                                          "(PLZ_id integer primary key autoincrement, " +
                                          "PLZ varchar(50), " +
                                          "Ort varchar(50), " +
                                          "Bundesland varchar(50), " +
                                          ");";


sqlite_cmd.ExecuteNonQuery();

string sql = "create table if not exists Titel" +
                                          "(Titel_id integer primary key autoincrement, " +
                                          "TitelKurz varchar(50), " +
                                          "TitelLang varchar(100), " +
                                          ");";

sqlite_cmd.ExecuteNonQuery();

string sql = "create table if not exists Anrede" +
                                          "(Anrede_id integer primary key autoincrement, " +
                                          "Anrede varchar(50), " +
                                          ");";

sqlite_cmd.ExecuteNonQuery();

Mit obigen Anweisungen dürften die Tabellen erstellt werden.

Mein Problem ist jetzt, bei den Postleitzahlen. Im WinForms erstellter Eingabemaske wird in der Textbox die PLZ eingetragen, dann sollte sich in der daneben befindlichen Combobox die Auswahlmöglichkeiten vorhanden sein. Wie bekannt ist, werden zu gleichen Postleitzahlen verschiedene Orte vorhanden sein. Darum funktioniert die PLZ nicht als id. Dann sollte die PLZ_id aus PLZ in die Personen PLZ_id eingetragen werden. Selbiges trifft natürlich auch auf die anderen Tabellen zu.

Da fehlt mir irgendwas.

Wer kann mir da weiter helfen, oder kann mir eine Quelle nennen, wo man es nachvollziehen kann. Das meiste was man findet, sind einzelne Tabellen, ist ab nicht sinnreich, denn da ist man auf dem Weg Redundanzen zu schaffen.

Schon einmal vielen Dank!

T
2.219 Beiträge seit 2008
vor 7 Jahren

Ich würde den Wohnort nicht auslagern.
Da sich der Wohhnort auch ändern kann, durch Umzug etc. hättest du ggf. noch verweiste Daten später in der Tabelle.
Ich würde den Wohnort als Teil der Person und somit direkt in der Personen Tabelle speichern.
Die Anrede + Titel würde ich aber auch auslagern.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.807 Beiträge seit 2008
vor 7 Jahren

Eine Person kann in den meisten Anwendungen mehrere Adressen haben, daher würde ich das auf alle Fälle über eine n:m Relation auslagern, sodass zb. eine Primär und Sekundär-Adresse wählbar ist.
Zudem, gehören Adressen in den meisten Anwendungen zu gewollten Redundanzen, zB. darf sich eine Adresse einer Rechnung im Nachhinein nicht mehr ändern, nur weil jemand umgezogen ist.
Auch gibt es heutzutage verschiedene Adresstypen (Hausadresse, Postfach, Packstation...), wobei das auf die Art und Weise der Anwendung ankommt.

Bedenke aber:
Es gibt in Deutschland Orte mit verschiedenen Postleitzahlen und kurioserweise auch Postleitzahlen mit mehreren Orten.
PLZ <> Ort ist also keine 1:1 Verbindung; das nur als Info.

D
985 Beiträge seit 2014
vor 7 Jahren

Für die Postleitzahlen erstellt man sich eine reine Lookup-Tabelle die keine Referenz zu den anderen Tabellen hat. Es handlet sich hier um einen komplett fremdgesteuerten Datenpool der auch nur die Eingabe vereinfachen soll.

LänderLookup

  • PK ISOCode
  • Name

OrteLookup:

  • PK Land_ISOCode
  • PK Postleitzahl
  • PK Ort
  • Bundesland

Die Beziehung Person zu Adresse sollte meiner Meinung allerdings 1:n und nicht n:m sein, denn unterschiedliche Personen teilen sich niemals die gleichen Adress-Datensätze.

So ungefähr:
Personen:

  • PK Id
  • Vorname
  • Nachname
  • ...

PersonAdressen:

  • PK Person_Id
  • PK AdressArt_Id
  • Strasse
  • ...

Und bei einer Rechnung werden die Adress-Informationen vom Kunden in die Rechnung kopiert und nicht referenziert (wie mein Vorredner korrekt ausgeführt hat)

dominik.jonczyk Themenstarter:in
13 Beiträge seit 2017
vor 7 Jahren

Erst einmal Danke soweit,

Es soll zur Probe eine kleine Adressenverwaltung sein. Also nicht für Versand und/ oder Rechnungsprogramme.

Wenn die Adresse der Person sich ändert, kann man das ganze über die update funktion recht gut realisieren:

string sql = "UPDATE Personen SET"...

wobei ich ja dann wieder selbiges problemchen wie bei der Insert habe.

Und es fängt wohl schon damit an, dass:

"FOREIGN KEY(PLZ_id) REFERENCES PLZ(PLZ_id), " +
"FOREIGN KEY(Anrede_id) REFERENCES Anrede(Anrede_id), " +
"FOREIGN KEY(Titel_id) REFERENCES Titel(Titel_id), " +

nicht funktionieren.

Liegt das an SQLite???

Hat jemand ein C# Projekt mit SQLite wonach mehrere Tabellen auch in Beziehung stehend, verwendet werden?
Oder kann mir jemand ein WebsiteLink zusenden wo man sich dies im Code anschauen kann.
Das würde mir echt weiter helfen.

D
985 Beiträge seit 2014
vor 7 Jahren

Bitte, wenn du Code postest, dann bitte in die Code-Tags setzen.

C#-Code => C# Code-Tags
XML und Konsorten => XML Code-Tags
SQL und der Rest => Code-Tags

Und wenn es eigentlich nur um SQL geht, dann doch bitte die Statements vom C# Grundrauschen befreien.

Statt


"FOREIGN KEY(PLZ_id) REFERENCES PLZ(PLZ_id), " +
"FOREIGN KEY(Anrede_id) REFERENCES Anrede(Anrede_id), " +
"FOREIGN KEY(Titel_id) REFERENCES Titel(Titel_id), " +

bitte so


FOREIGN KEY(PLZ_id) REFERENCES PLZ(PLZ_id),
FOREIGN KEY(Anrede_id) REFERENCES Anrede(Anrede_id),
FOREIGN KEY(Titel_id) REFERENCES Titel(Titel_id),

dann könnte man sich eventuell auch mal hinreißen lassen und diese SQL-Statements schnell mal eben per Copy'Paste auf eine Datenbank zu werfen.

Wenn man aber da erst mit dem Besen dran muss, geht das Verlangen deutlich gegen 0 (und drunter)

16.807 Beiträge seit 2008
vor 7 Jahren

Und nen Tipp allgemein:

vermeide SQL Befehle jeglicher Art als String.
Für den Aufbau von Tabellen mit Sqlite ist FluentMigrator super geeignet.

dominik.jonczyk Themenstarter:in
13 Beiträge seit 2017
vor 7 Jahren

nochmals vielen Dank für die Hinweise!!!

@Sir Rufo
Das mit dem Code-Tag habe ich nicht gewußt, werde ich natürlich künftig beherzigen.
Wollte es doch tatsächlich hier mal gleich ausprobieren, ob ich es auch gleich richtig mache:

"FOREIGN KEY(PLZ_id) REFERENCES PLZ(PLZ_id), " +
"FOREIGN KEY(Anrede_id) REFERENCES Anrede(Anrede_id), " +
"FOREIGN KEY(Titel_id) REFERENCES Titel(Titel_id), " +
FOREIGN KEY(PLZ_id) REFERENCES PLZ(PLZ_id),
FOREIGN KEY(Anrede_id) REFERENCES Anrede(Anrede_id),
FOREIGN KEY(Titel_id) REFERENCES Titel(Titel_id),

Nur den Hinweis mit dem >> Code(SQLite): << habe ich nicht hinbekommen. Das dürfte für den Leser auch recht hilfreich sein, statt nur Code. Auch wenn man an der Syntaax erkennen dürfte , dass es SQL Befehle sind.

@Abt
Der Hinweis auf den FluentMigrator ist mir neu, werde ich in den kommenden Stunden antesten. Danke für den Hinweis.

dominik.jonczyk Themenstarter:in
13 Beiträge seit 2017
vor 7 Jahren

Und nen Tipp allgemein:

vermeide SQL Befehle jeglicher Art als String.
Für den Aufbau von Tabellen mit Sqlite ist
>
super geeignet.

Der Fluentmigrator wird häufig empfohlen, auch hier im Forum.

Das ist für mich totales Neuland, gibt es ein Skript, wonach man sich eine eigene Datenbankanwendung zusammenbauen kann. So als Einstieg...

F
10.010 Beiträge seit 2004
vor 7 Jahren

Wenn du dir den Code bei Github anschaust, da gibt es auch ein Verzeichnis FluentMigrator.Example

dominik.jonczyk Themenstarter:in
13 Beiträge seit 2017
vor 7 Jahren

hier habe ich ein Anfang als Lösung, fehlen nur noch die Datenbindungen 😉
darum meine Bitte, schaut mal drüber ob es soweit richtig ist.


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SQLite;


namespace AdressenVerwaltung
{
    public partial class Form1 : Form
    {
        
        private SQLiteConnection conn = new SQLiteConnection("Data Source=" + AppDomain.CurrentDomain.BaseDirectory + "AdressenVerwaltung.sqlite");

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                conn.Open();//hier wird die DB erzeugt, wenn sie noch nicht da ist
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.GetType() + ": Datenbank kann nicht erzeugt werden! - weiter mit OK");
                conn.Close();
            }
            conn.Close();
            //hier wird die Tabellen Personen, Anrede, Titel und PLZ angelegt, wenn sie noch nicht vorhanden ist
            try
            {
               string sql1 = "CREATE TABLE IF NOT EXISTS Personen" +
                                           "(Personen_ID INTEGER PRIMARY KEY AUTOINCREMENT," +
                                           "Vorname NVARCHAR(100)," +
                                           "Nachname NVARCHAR(100)," +
                                           "Strasse NVARCHAR(100)," +
                                           "Telefon NVARCHAR(50)," +
                                           "PLZ_ID INTEGER NOT NULL," +
                                           "Anrede_ID INTEGER," +
                                           "Titel_ID INTEGER);";
                
                string sql2 = "CREATE TABLE IF NOT EXISTS Anrede" +
                                          "(Anrede_ID INTEGER PRIMARY KEY AUTOINCREMENT," +
                                          "Anrede NVARCHAR(100)," +
                                          "FOREIGN KEY(Anrede_ID) REFERENCES Personen(Anrede_ID));";
                                        
                string sql3 = "CREATE TABLE IF NOT EXISTS Titel" +
                                          "(Titel_ID INTEGER PRIMARY KEY AUTOINCREMENT," +
                                          "Titel NVARCHAR(100)," +
                                          "FOREIGN KEY(Titel_ID) REFERENCES Personen(Titel_ID));";
                                        
                string sql4 = "CREATE TABLE IF NOT EXISTS PLZ" +
                                          "(PLZ_ID INTEGER PRIMARY KEY AUTOINCREMENT," +
                                          "PLZ NVARCHAR(100)," +
                                          "Ort NVARCHAR(100)," +
                                          "Bundesland NVARCHAR(100)," +
                                          "FOREIGN KEY(PLZ_ID) REFERENCES Personen(PLZ_ID));";
                                         
                //string sql5 = "select * from Personen";

                string sql = sql1 + sql2 + sql3 + sql4;

                
                SQLiteCommand cmd = new SQLiteCommand(sql, conn);
                conn.Open();
                cmd.ExecuteNonQuery();
               // SQLiteDataAdapter da = new SQLiteDataAdapter(sql5, conn);
               // DataTable dt = new DataTable();

                
               // da.Fill(dt); // der DataAdapter befüllt die DataTable

               // dataGridView1.DataSource = dt;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.GetType() + ": Die Datentabelle kann nicht angelegt oder gefunden werden! - weiter mit OK");
                conn.Close();
            }
            conn.Close();
        
    
        }
    }
}

16.807 Beiträge seit 2008
vor 7 Jahren

Ob etwas richtig is merkste ja ganz einfach, wenns einen entsprechenden Fehler gibt.
Logisch kannst es ja selbst überprüfen 😉

Mit Fluent Migrator hast Du es trotzdem einfacher. Würde nie so eine String Frickelei mehr machen.

dominik.jonczyk Themenstarter:in
13 Beiträge seit 2017
vor 7 Jahren

Da der Code ordnungsgemäß ausgeführt worden ist, kann man davon ausgehen, dass im C# Code auch kein Fehler ist.
Vielleicht habe ich meine Frage schlecht oder zu kurz ausgeführt. Ich bat lediglich um Prüfung, ob die Tabellenbeziehung so richtig aufgebaut sind, so wie die Grafik es zeigt (siehe mein erster Beitrag).

Mit dem Fluent Migrator würde ich ja sehr gern arbeiten wollen, da fehlt mir irgend wie der Einstieg als Anfänger 😉

Hinweis von Abt vor 7 Jahren

Keine Full-Quotes

T
2.219 Beiträge seit 2008
vor 7 Jahren

@dominik.jonczyk
Am besten nutzt du bei mehrzeiligen Strings einen Literal.

Bsp:


string sql2 = @"
CREATE TABLE IF NOT EXISTS Anrede
(
    Anrede_ID INTEGER PRIMARY KEY AUTOINCREMENT, 
    Anrede NVARCHAR(100),
    FOREIGN KEY(Anrede_ID) REFERENCES Personen(Anrede_ID)
);
";

Ist leserlicher und macht auch das suchen nach Fehlern einfacher.
Ansonsten sehen deine Tabellen vom Aufbau her korrekt aus.
Da ein Test deines Codes auch erfolgreich war, dürfte hier alles passen.
Am besten noch einen Testlauf mit Daten machen und deinen UI und DB Code noch trennen nach dem Drei Schichten Modell.
Dann sollte alles passen.

T-virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

dominik.jonczyk Themenstarter:in
13 Beiträge seit 2017
vor 7 Jahren

Ist leserlicher und macht auch das suchen nach Fehlern einfacher.

Sieht wirklich übersichtlicher aus, werde ich mal gleich mit umsetzen.
Meinst Du mit UI und DB Code noch trennen, dass eigene Klassen anzulegen sind?

Hinweis von Coffeebean vor 7 Jahren

Keine Full-Quotes bitte [Hinweis] Wie poste ich richtig?

D
985 Beiträge seit 2014
vor 7 Jahren

Die einfachste Prüfung ob man in einer Klasse zuviel hineingewurschtelt hat ist die Benennung der Klasse, wo aus dem Namen hervorgeht was die Klasse macht.

Hier wäre es z.B. AdressDbErzeugungAbfrageAdressAnzeigeForm 😉
(Hört sich komisch an und damit macht diese Klasse zuviel)

dominik.jonczyk Themenstarter:in
13 Beiträge seit 2017
vor 7 Jahren

Stimmt.

In der Umschulung haben wir es eben so gelernt bekommen, jetzt vor meiner Projektarbeit, fällt es mir eben auf, dass der Weg so nicht richtig ist.

Und da haben wir auch noch dazu mit nur einer Tabelle gearbeitet.

Jetzt muss ich mir einen Weg suchen... was ja so einfach nicht ist.
Aber schön das es ein C# Forum gibt, wo man den ein oder anderen Hinweis bekommen kann. 😉

Danke erst einmal für die Antworten!

T
2.219 Beiträge seit 2008
vor 7 Jahren

@dominik.jonczyk
Da die meisten hier auch angestellte Entwickler sind die auch im Team arbeiten, haben wir auch hier gewisse Grundsätze was sauberen Code angeht.

Dazu gehört auch die Schichtentrennung um sowohl Redundanz aufzulösen sowie die die Vereinheitlichung des Codes durch saubere Kapselung und Aufteilung.
Das Drei Schichten Modell ist hier ein guter Ansatz um die Anwendungslogik, die Datenschicht sowie die Definitionsobjekte zu trennen.

Dies bringt auch den Vorteil, dass die Schichten Austauschbar sind.
Gerade wenn man eine Datenschicht für eine bestimmte DB umgesetzt hat und man nun einen Umstieg machen muss, kann man die Datenschicht neu umsetzen und einfach austauschen ohne das es eine Änderung an den zugehörigen Schnittstellen gibt.

Aktuell geht aber auch dort der Trend stark wieder in Richtung OR Mapper, was die Austauschbarkeit weiter vereinfachen kann.
Aber da hier Fix mit Sqlite gearbeitet wird, würde ich erst einmal noch mit den entsprechend Wrapper Klasen und einem Drei Schichten Modell arbeiten.
Dann kannst du deine Sql Anweisungen in der Datenschicht lagern und über die Application Schicht diese verarbeiten lassen.

Einen entsprechenden Artikel zu dem Thema haben wir auch 😃
[Artikel] Drei-Schichten-Architektur

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

dominik.jonczyk Themenstarter:in
13 Beiträge seit 2017
vor 7 Jahren

@T-Virus:
...wie aber auch in der Diskusion des drei Schichtenmodells nachvollziehbar, gibt es auch Nachteile. Aber trotz dessen sollte man schon an sich arbeiten, dass man sauberen Code schafft. Und meine Meinung dazu ist, dass man diesen auch dokumentiert.
Dies tut man sicherlich nicht nur, um im besser Team zu arbeiten, sodern eben auch für sich selber...

Mein Projekt nimmt nun doch tatsächlich gute Form an, so habe ich um Redundanzen zu vermeiden, zwei Methoden geschaffen, die super gut funktionieren:


// ExecuteScalar liefert Einzelwerte
        public object myExecuteScalar(string sql)
        {
            SQLiteCommand cmd = new SQLiteCommand(sql, conn);

            conn.Open();
            object foo = cmd.ExecuteScalar().ToString();
            conn.Close();

            return foo;
        }

        public void myExcuteNonQuery(string sql)
        {
            SQLiteCommand cmd = new SQLiteCommand(sql, conn);

            conn.Open();
            cmd.ExecuteNonQuery();
            conn.Close();
        }

Hier ein Beispiel zur Anwendung der myExcuteNonQuery Methode:


myExcuteNonQuery(@"
                CREATE TABLE IF NOT EXISTS Personen
                (
                    Personen_ID INTEGER PRIMARY KEY AUTOINCREMENT,
                    Vorname NVARCHAR(100),
                    Nachname NVARCHAR(100),
                    Strasse NVARCHAR(100),
                    Telefon NVARCHAR(50),
                    PLZ_ID INTEGER,
                    Anrede_ID INTEGER,
                    Titel_ID INTEGER
                );
                ");

und hier ein Beispiel zur Anwendung der myExecuteScalar Methode:


Int32 count1 = Convert.ToInt32(myExecuteScalar("SELECT COUNT(*) FROM Anrede").ToString());
                if (count1 < 2)
                {
                    myExcuteNonQuery(@"
                INSERT INTO Anrede(Anrede)VALUES
                (
                    'Frau'
                );
                ");

                    myExcuteNonQuery(@"
                INSERT INTO Anrede(Anrede)VALUES
                (
                    'Herr'
                );
                ");

                }

Wie man an diesen Ansatz erkennen kann, dürfte ich auf den richtigen Weg sein. Wenn ich mehr als nur zwei Methoden haben, werde ich dass ganze in eine Datenbankklasse auslagern.

Jetzt bin ich auf der Suche zur Realisierung die PLZ Tabelle mittels einer vorliegenden CSV Datei zu befüllen.

Insert a csv file into sqlite

Denn mit obiger vorliegender Methode ca. 13500 Datensätze zu befüllen, dürfte sinnfrei sein. Darum der Weg über die CSV Datei.
Wie ich hier im Forum gelsen habe, wurde dies schon mal besprochen, jedoch habe ich die Quelle od. die entsprechende Diskusion nicht gefunden.

Ebenso habe ich viele Hinweise gefunden, die auf den Fluent Migrator hinweisen, aber wenn man sich auf der Suchze begibt, die es einem kurz und bündig erklärt, verliefen bei mir bislang negativ.

@Abt:
Das ist, wie ich finde, sehr schade! Wäre schön von Dir, wenn Du ein kleines deutschsprachiges Tutorial einstellst, wie Du damit am besten arbeitest. Denn ähnlich gelagerte Fragen von mir sind hier schon häufiger aufgekommen und nur der Hinweis auf Fluent Migrator ist nicht ausreichend.

@T-Virus:
Ich arbeite daran auch im Team sauber zu arbeiten. Bin gegenwärtig im Praktikum. Doch leider beschäftigen sich meine Kollegen mit anderen Thematiken und haben von der Datenbankentwicklung nicht viel Ahnung.

Also erst einmal Danke bis hierher.

D
985 Beiträge seit 2014
vor 7 Jahren

Also wenn ich so eine Anwendung baue, dann erstelle ich mir ein Model z.B. Person und einen DataService z.B. IPersonService.

Um mit der Anwendung weitermachen zu können gibt es zu dem DataService eine Fake-Implementierung z.B. FakePersonService. Dort werden einfach nur statische Inhalte ausgeliefert.

Damit kann man prinzipiell die gesamte Anwednung fertigstellen und dann entscheidet man sich, wie denn diese Persistenz-Schicht realisiert wird, denn erst jetzt hat man ein Gesamtbild und weiß, was alles und in welchem Zusammenhang gespeichert werden muss (und ob es wirklich eine Datenbank sein muss).

C
26 Beiträge seit 2016
vor 7 Jahren

Hallo Dominik,

du baust gerade einen "Wrapper" für SQLite.
Die gibt es aber schon, schau Dir mal NPoco oder Dapper an.

Damit kannst Du dann die von Rufo erwähnte Person-Klasse mit Daten füllen.

dominik.jonczyk Themenstarter:in
13 Beiträge seit 2017
vor 7 Jahren

@Sir Rufo:
Das Ding mit MVVM, davon habe ich mal gehört, jedoch bislang nicht gelernt. Sicherlich geht dann alles leichter von der Hand.
Erst jetzt, wie ich vor der Projektarbeit stehe, merke ich wieviele Wissenlücken, mir die Umschulung hinterlassen hat. Sicher kann die Schule behaupten, dass man nicht alle Themengebiete abdecken kann. Jedoch wie ich feststelle, haben wir lediglich "Bullshit" gelernt bekommen.
Ohne jeglichen Praxisbezug. Dadurch habe ich es jetzt sehr schwer in dieser kurzen Zeit mir alles zu erarbeiten.
Z.B. haben wir uns die Möglichkeiten von Linq überhaupt nicht angesehen. ADO außerdem sehr oberflächlich, wie man hier erkennen mag 😉
Mein Projektarbeit ließe sich mit an Sicherheit grenzender Wahrscheinlichkeit für ein Profi wie Du es jetzt bist, in max. 8h Stunden erarbeiten, dann jedoch sicherlich noch richtig schön mit WPF 😉
OK, vielleicht habe ich mit 8h schon zuviel angesetzt...

@codesoldier
vielen Dank für die Hinweise auf die Wrapper, werde ich mir gleich mal anschauen

D
985 Beiträge seit 2014
vor 7 Jahren

Von MVVM habe ich doch gar nicht gesprochen, und das was ich dort anspreche ist auch in keinster Weise MVVM. Ich beschreibe lediglich die Trennung zwischen der Anwendungs-Schicht (wie immer die auch realisiert ist) und der Persistence-Schicht.

dominik.jonczyk Themenstarter:in
13 Beiträge seit 2017
vor 7 Jahren

Jetzt bin ich auf der Suche zur Realisierung die PLZ Tabelle mittels einer vorliegenden CSV Datei zu befüllen.

Da es eine häufige Problematik ist, ich sonst wo nichts weiter gefunden habe, vielleicht habe ich nicht die richtigen Suchworte bei Google bemüht und weil es hier keine weiteren Anregungen gab, die zu einer Lösung führen, habe ich mal ein Beispiel zusammengeklimmpert.
Einziger Kuhfuß ist, dass ich die Kopfzeile von der CSV Datei mit importiere, etwas unschön. Da fehlt mir noch eine Lösung, an der ich mich morgen ran mache.


using System;
using System.Text.RegularExpressions;
using System.Collections;
using System.IO;
using System.Data.SQLite;

namespace ImportCVSintoSQLite
{
    class Program
    {
        static void Main(string[] args)
        {
            Regex splitRx = new Regex(@";\s*", RegexOptions.Compiled);
            ArrayList al = new ArrayList();

            using (StreamReader sr = new StreamReader(AppDomain.CurrentDomain.BaseDirectory + "Namen.csv"))
            {
                string line = null;
                int ln = 0;
                while ((line = sr.ReadLine()) != null)
                {
                    string[] fields = splitRx.Split(line);
                    if (fields.Length != 3)
                    {
                        continue;
                    }
                    ln++;
                    al.Add(fields);
                }
            }

            using (var conn = new SQLiteConnection("Data Source=" + AppDomain.CurrentDomain.BaseDirectory + "Namen.sqlite"))
            {
                conn.Open();

                using (var cmd = new SQLiteCommand(conn))
                {
                    cmd.CommandText = "CREATE TABLE IF NOT EXISTS Personen" +
                                           "(Personen_ID INTEGER PRIMARY KEY AUTOINCREMENT," +
                                           "Vorname NVARCHAR(100)," +
                                           "Nachname NVARCHAR(100)," +
                                           "GeburtsName NVARCHAR(100));";
                    cmd.ExecuteNonQuery();

                    using (var transaction = conn.BeginTransaction())
                    {
                        foreach (string[] sa in al)
                        {
                            cmd.CommandText =
                                "INSERT INTO Personen (Vorname, Nachname, GeburtsName) VALUES ('" + sa[0] + "', '" + sa[1] + "', '" + sa[2] + "');";
                            cmd.ExecuteNonQuery();
                        }

                        transaction.Commit();
                    }
                }

                conn.Close();
            }
        }
    }
}

16.807 Beiträge seit 2008
vor 7 Jahren

Auch hier: keine String Frickelei.Das musst Du Dir unbedingt abgewöhnen, ansonsten wirst Du immer anfällige, schlechte Software schreiben =)
[Artikelserie] SQL: Parameter von Befehlen

Und Finger weg von untypisierten Elementen wie der ArrayList
Das gleiche gilt für Pfade, die frickelt man auch nicht zusammen, sondern verwendet Path.Combine.

D
985 Beiträge seit 2014
vor 7 Jahren

Und bei CVS würde ich auch nichts finden, aber bei CSV da findet man z.B. filehelpers.net

dominik.jonczyk Themenstarter:in
13 Beiträge seit 2017
vor 7 Jahren

@Abt:

String Frickelei.Das musst Du Dir unbedingt abgewöhnen,...

Bislang habe ich da keine andere Möglichkeit gefunden, da auch nicht anders gelernt bekommen.

untypisierten Elementen wie der ArrayList...

Das war aus meiner Sicht der beste Lösungsweg, die Daten aus der CSV zuverlässig in die SQLite Datenbank zu bekommen. Und mein Test hat es bewiesen, dass es sehr gut funktioniert. Trotz der Hürden mit der String Frickelei und den ArrayList

aber hier habe ich einen Superguten Ansatz erhalten

@Sir Rufo
filehelpers.net werde ich mir mal näher ansehen

Danke Euch beiden, neben der Knappen Zeit die Euch verbleibt, hier an dieser Stelle den ein oder anderen guten Ratschlag zu geben, auch wenn ich noch nicht alles so umsetzen kann wie von Euch vorgeschlagen. Aber ich lerne ja noch und vor allem sehr gerne 😉

Hinweis von Coffeebean vor 7 Jahren

Kannst du bitte, wenn du schon zitierst, auch die Code-Tags verwenden?