Laden...

SQLite (Mehrere User updaten denselben Eintrag - Was passiert?)

Erstellt von Moritz83 vor 4 Jahren Letzter Beitrag vor 4 Jahren 1.785 Views
M
Moritz83 Themenstarter:in
50 Beiträge seit 2013
vor 4 Jahren
SQLite (Mehrere User updaten denselben Eintrag - Was passiert?)

Hallo,

ich habe vor einiger Zeit eine MS Access Lösung für unsere Abteilung erstellt (Zeiterfassung, ganz simples Projektmanagement mit IN / OUT Kennzahlen) und würde diese gerne in C# und SQLite umsetzen. Fange gerade erst wieder an mit C# und bin im Moment am Lesen und ausprobieren.

Momentan habe ich folgendes Beispiel erstellt (das Ganze ist an ein WPF Datagrid angebunden) was auch wunderbar funktioniert.

using System.Data;
using System.Windows;
using System.Data.SQLite;
using System;

namespace WPF_MySQL_Connection
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public DataTable Dt;
        public MainWindow()
        {
            InitializeComponent();
            string connectionString = "Data Source=" + AppDomain.CurrentDomain.BaseDirectory + "Test.db" + ";Version=3;";
            SQLiteConnection connection = new SQLiteConnection(connectionString);
            SQLiteCommand cmd = new SQLiteCommand("select * from Test", connection);
            connection.Open();
            Dt = new DataTable();
            Dt.Load(cmd.ExecuteReader());
            //connection.Close();
            dtGrid.DataContext = Dt;
        }

        public void SaveChanges(object sender, RoutedEventArgs e)
        {
            string connectionString = "Data Source=" + AppDomain.CurrentDomain.BaseDirectory + "Test.db" + ";Version=3;";
            SQLiteConnection connection = new SQLiteConnection(connectionString);
            var abc = new SQLiteDataAdapter("select * from Test", connection);
            SQLiteCommandBuilder builder = new SQLiteCommandBuilder(abc);
            abc.UpdateCommand = builder.GetUpdateCommand();
            abc.Update(Dt);

        }
    }
}

Aus der Tabelle "Test" lese ich im Moment den Wert "Name" aus und stelle ihn im Datagrid dar. Wenn ich den nun editiere und via Button (Click Method "SaveChanges") wieder speichere taucht die Änderung im db File auf. Hiezu nun 2 Fragen:

1.) Gehe ich Recht in der Annahme dass wenn ein 2. User zur gleichen Zeit denselben Eintrag ändert das erst eine und danach die andere Änderung vorgenommen wird? (Sprich die Tabelle wird für kurze Zeit gesperrt bis der Updateprozess abgeschlossen ist und dann wird das nächste Update vollzogen)
2.) Es sind mehr oder weniger statische Daten mit sehr wenig Änderungen pro Stunde, wie könnte man ein Update des UI vornehmen? (Gibt es eine Möglichkeit das die SQLite Datei ein "Signal" sendet wenn eine Tabellle geändert wurde so das alle die zu dem Zeitpunkt ein Datagrid der entsprechenden Tabelle sehen ein Update kriegen?) (Hoffe das ist verständlich ausgedrückt 🙁 )

Danke euch im Vorraus!

Gruss
Moritz

PS: Wie gesagt, blutiger Anfänger ... der Code oben ist alles andere als "regelkonform" 😉

16.807 Beiträge seit 2008
vor 4 Jahren

Locking Mechanismen musst Du selbst implementieren; nimmt Dir die Datenbank nicht ab.

Bei Punkt 2 würde man mit Events arbeiten; zB. mit Reactive Extensions.
D.h. wenn Du die Datenbank schreibst, wirfst Du Applikationsintern einen Event.
Das lässt sich super einfach realiseren, wenn Du allgemein Deine Anwendung nach Events auslegst, zB. mit Hilfe von MediatR.

Aber ja, wenn das neu ist, dann muss man sich erst mal einlesen.
Beispiele zu MediatR siehst Du zB. bei mir im GitHub.
https://github.com/BenjaminAbt/2018-Talks-ModernApiDevelopment/tree/master/src/Common.Engine

Und da Du mit WPF arbeitest: [Artikel] MVVM und DataBinding
Verwendest Du bei WPF kein MVVM, dann wirst Du sehr schnell mit Hacks arbeiten müssen - was unsauber wird.
WPF ist auslegt um mit MVVM zu arbeiten.

T
2.219 Beiträge seit 2008
vor 4 Jahren

Was du machen willst, wird nicht mit einer Embedded DB wie Sqlite gelöst.
Wenn du eine Zeiterfassung machst, dann nimm einen richten DB Server der die Daten dann zentral lagert.
Sqlite ist nicht dafür gedacht, dass X Benutzer darauf einhauen mit Daten.
Embedded DBs sollten immer als Stand-Alone Datenbanken verwendet werden.

In deinem Fall würde ich eine Web als API aufsetzen gegen das deine Anwendung als Client per WebServices arbeitet.
Das sauber umgesetzt, löst auch viele Probleme wie die Synchronisation der Sqlite Datenbanken und weitere Fehlerquellen.
Zusätzlich verbirgst du damit deine Datenbank vor Einblicken und Manipulation.
Sqlite Datenbanken kann man mit den entsprechenden Tools einfach bearbeiten.

Ebenfalls gehören SQL Anweisungen nicht in die UI.
Siehe Drei-Schichten-Modell für die saubere Trennung von Datenmodell, Datenverarbeitung und der Anwendungslogik.

Auch solltest du das DataTable nicht als Container für deine Daten verwenden.
Bau dir eine entsprechende Klasse die dann deine Daten abbilden und arbeite damit.
DataTable sind schwerfällige und Speicherintensive Konstrukte, wenn möglich immer meiden.

Deinen ConnectionString solltest du auch dann in der App.config bzw. bei einem Web in die Web.config packen.
Sowas gehört nicht hart gecoded.

SqliteConnections solltest du in ein using packen, damit diese automatisch disposed werden.
Im schlimmsten Fall gibst du die Verbindung nicht frei und sperrst dir damit den Zugriff auf deine Datei.

Nachtrag:
Wenn der aktuelle Ansatz nur zum testen und lernen ist, ist es noch okay.
Wenn möglich versuch aber schon einmal diese Puntke aufzunehmen und dir anzuschauen.
Gerade bei größeren Projekten wirst du dich später freuen wenn dein Code noch wartbar und erweiterbar ist. 😃

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 4 Jahren

Sqlite ist nicht dafür gedacht, dass X Benutzer darauf einhauen mit Daten.

Doch, Sqlite kann problemlos von mehreren Prozesse, Threads und auch von mehreren Usern zeitgleich verwendet werden - anders als Access.

In deinem Fall würde ich eine Web als API aufsetzen gegen das deine Anwendung als Client per WebServices arbeitet.

In meinen Augen absoluter Overkill.
Es geht hier um eine simple Zeiterfassung wie er bereits schreibt.

Nicht um Zeiterfassung von Mitarbeitern am Stempelautomat.
Aber ja, damit sind natürlich nicht alle technischen Fallstricke gelöst.

Das sauber umgesetzt, löst auch viele Probleme wie die Synchronisation der Sqlite Datenbanken und weitere Fehlerquellen.

Nein, es löst kein Locking Szenario von Einträgen.

M
Moritz83 Themenstarter:in
50 Beiträge seit 2013
vor 4 Jahren

Erstmal danke euch Beiden! Vielleicht noch als Info, ich bin kein Informatiker sondern möchte mir C# in "Eigenregie" aneignen um dann diese Kenntnisse bei uns im Büro ev. umsetzen zu können. Wir haben leider keine eigene IT und unsere Geschäftsleitung ist der Meinung das Excel genügt

Wir brauchen mittelfristig def. eine professionelle Lösung (also nicht meine Variante) aber solche Prozesse dauern bei uns Jahre. Da die Access Lösung läuft tu ich dies in erster Linie für Mich und meinen Spieltrieb, sprich so schnell wird da nix in den laufenden Betrieb eingebaut.

@Abt
MVVM steht ganz oben auf meiner ToDo Liste, allerdings übe ich im Moment noch mit den grundlegenden C# Befehlen und wollte da noch ein wenig mehr üben (meine Logik: Wenn ich den Befehl beisammen habe und es funktioniert kann ich es im 2. Schritt entsprechend den MVVM Regeln umsetzen).

Wollte erstmal gucken wie das mit dem Binding funktioniert und der nächste Schritt wäre dann die Umsetzung dieses Miniprojekts mit dem MVVM Pattern. So möchte ich Step-by-Step mein Wissen erweitern.

@T-Virus
Vielleicht zur Erklärung zum Thema "Zeiterfassung":
Wir generieren für jeden Auftrag in unserer Abteilung eine eindeutige Nummer (K + Laufnummer), erfassen diverse Schritte wie "Genehmigungszeichnung, Freigabe oder Änderung" mit jeweils In / Out Datum und zu jedem Schritt werden Arbeitszeiten erfasst (Beispiel: K1500 / Freigabe / 10.04.2019 + 11.04.2019 / 3h) und das wars. Wir reden hier von ca. 3-6 Nummern pro Tag, mehr auf keinen Fall und es arbeiten ca. 15 Leute damit wobei die Chance das 2 Personen denselben Auftrag bearbeiten bei max. 1% liegt.

Das MVVM Pattern ist, wie oben geschrieben, ganz oben auf meiner ToDo Liste, aber ich "kämpfe" im Moment noch mit C# selber (Befehle, Aufbau, etc).

Nehme aber eure Punkte sehr gerne auf und werde mich def. damit in Kürze beschäftigen.

M
Moritz83 Themenstarter:in
50 Beiträge seit 2013
vor 4 Jahren

Danke für den Link zu den Layern, macht absolut Sinn die Aufteilung!

Habe heute ein wenig gelesen und das Beispiel studiert. Wollte dann mich mit dem Thema "ObservableCollection" befassen, allerdings finde ich dazu in Zusammenhang mit SQLite kaum Beispiele und die meisten lesen die Daten aus SQLite in ein Datatable und wandeln das dann um ... kommt mir seltsam vor diesen Zwischenschritt zu machen! (Oder ist das wirklich die Vorgehensweise?)
Hat jemand hierzu ein "besseres" Beispiel?

Das Thema mit dem "using" bei SQL Verbindungen und das verwalten des Connectionstrings habe ich Gott sei Dank etwas besser kapiert.

4.931 Beiträge seit 2008
vor 4 Jahren

Eine DataTable wird in den meisten Tutorials und Beispielen eher der Einfachheit benutzt (bzw. auch aus Unerfahrenheit 😉, ist aber nicht der beste Weg.

Da wären eher Repository und Unit of Work die passenden Stichworte.

Wenn du jedoch erst einmal eher ein kleines bis mittleres Projekt angehst, dann solltest du auch nicht zu viele Design-Patterns gleichzeitig angehen, sondern nach und nach dich mit den verschiedenen Themen befassen (sonst kann es manchmal eher als "Overengineering" angesehen werden).

M
Moritz83 Themenstarter:in
50 Beiträge seit 2013
vor 4 Jahren

das mit dem Overengineering kenne ich von der Access Lösung her, wollte viel mehr als ich "packen" kann.

Naja dachte mir halt das ich (eben weill die DB mein zentrales Element ist) gleich auf etwas setzen sollte das mehr "wumms" hat. Ich guck mir das Thema Repository mal an, danke dir