myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » Code-Reviews » SQL-Befehl (String) aus Klasse und Attribute erstellen
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

SQL-Befehl (String) aus Klasse und Attribute erstellen

 
Beiträge zu diesem Thema Autor Datum
 SQL-Befehl (String) aus Klasse und Attribute erstellen resper 08.06.2017 19:19
 RE: SQL-Befehl (String) aus Klasse und Attribute erstellen gfoidl 08.06.2017 20:07
 RE: SQL-Befehl (String) aus Klasse und Attribute erstellen resper 09.06.2017 00:03
 RE: SQL-Befehl (String) aus Klasse und Attribute erstellen Stefan.Haegele 09.06.2017 07:52
 RE: SQL-Befehl (String) aus Klasse und Attribute erstellen gfoidl 09.06.2017 09:12
 RE: SQL-Befehl (String) aus Klasse und Attribute erstellen resper 09.06.2017 19:49
 RE: SQL-Befehl (String) aus Klasse und Attribute erstellen FZelle 09.06.2017 13:06
 RE: SQL-Befehl (String) aus Klasse und Attribute erstellen FZelle 10.06.2017 13:14
 RE: SQL-Befehl (String) aus Klasse und Attribute erstellen RED-BARON 26.06.2017 22:32
 RE: SQL-Befehl (String) aus Klasse und Attribute erstellen Deaktiviertes Profil 26.06.2017 22:43

Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
resper
myCSharp.de-Mitglied

Dabei seit: 15.02.2017
Beiträge: 33
Entwicklungsumgebung: Visual Studio
Herkunft: Kassel


resper ist offline

SQL-Befehl (String) aus Klasse und Attribute erstellen

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

Leider ist mir für diesen Beitrag kein andere Titel eingefallen. Wie bereits aus meinen anderen Beiträgen ersichtlich beschäftige ich mich momentan mit der Integration von SQLlite in mein kleines Programm. Dazu bastel ich an eine Klasse für meine SQLite Operationen, die ich evtl. später auch für andere Projekte nutzen kann. Ähnlich wie bei der SQLite-net habe ich eine Methode, dass mir erlaubt aus Models Tabellen zu erstellen. Mich würde interessieren, wie die Profis unter Euch meine aktuelle Methode beurteilen und was ich evtl. verbessern könnte. Dabei geht es nicht direkt um die SQLite Funktion, der String der erzeugt wird macht als SQLite Befehl, das was er soll, sonder rein um den Weg zum String.

Meine Klasse für die Attribute:

C#-Code:
class DbAttributes : Attribute
{
    public bool IsPrimary { get; set; }
    public bool IsAuto { get; set; }
    public bool IsInteger { get; set; }
    public bool IsText { get; set; }
}

Beispiel eines Models:

C#-Code:
    class User
    {
        [DbAttributes(IsPrimary =true, IsAuto =true, IsInteger =true)]
        public long Id { get; set; }
        [DbAttributes(IsText =true)]
        public string Login { get; set; }
        [DbAttributes(IsText = true)]
        public string Firstname { get; set; }
        [DbAttributes(IsText = true)]
        public string Lastname { get; set; }
        [DbAttributes(IsText = true)]
        public string PersId { get; set; }
        [DbAttributes(IsText = true)]
        public string Password { get; set; }
        [DbAttributes(IsInteger =true)]
        public long Role { get; set; }
        [DbAttributes(IsInteger = true)]
        public long First { get; set; }
        [DbAttributes(IsInteger = true)]
        public long Active { get; set; }
    }

Meine Methode:

C#-Code:
private void createTable<T>()
{
    PropertyInfo[] props = typeof(T).GetProperties();
    string[] cols = new string[props.Count()];
    for(int i = 0; i < props.Count(); i++)
    {
        string colString = String.Format("'{0}'", props[i].Name);
        var attrs = props[i].GetCustomAttributes(true);
        foreach (DbAttributes attr in attrs)
        {
            colString += (attr.IsInteger) ? " INTEGER" : "";
            colString += (attr.IsText) ? " TEXT" : "";
            colString += (attr.IsPrimary) ? " PRIMARY KEY" : "";
            colString += (attr.IsAuto) ? " AUTOINCREMENT" : "";
        }
        cols[i] = colString;
    }
    string createTable = String.Format("CREATE TABLE IF NOT EXISTS '{0}' ({1});", typeof(T).Name, String.Join(", ", cols));

    queryNon(createTable);
}

C#-Code:
createTable<User>();

erzeugt dann folgenden String

Zitat:
CREATE TABLE IF NOT EXISTS 'User' ('Id' INTEGER PRIMARY KEY AUTOINCREMENT, 'Login' TEXT, 'Firstname' TEXT, 'Lastname' TEXT, 'PersId' TEXT, 'Password' TEXT, 'Role' INTEGER, 'First' INTEGER, 'Active' INTEGER);


mycsharp.de  Moderationshinweis von gfoidl (08.06.2017 19:57):

Ich hab den Titel leicht angepasst, so dass es (ein bischen) klarer wird.
 
08.06.2017 19:19 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
gfoidl gfoidl ist männlich
myCSharp.de-Team

avatar-2894.jpg


Dabei seit: 07.06.2009
Beiträge: 6.651
Entwicklungsumgebung: VS 2019
Herkunft: Waidring


gfoidl ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo resper,

ein paar Anmerkungen dazu:
  • ich würde die Model-Klassen (hier User) frei von den DB-Attributen lassen, damit diese "universeller" einsetzbar sind. Aktuell haben diese Klassen einen Bezug zu "deiner" Datenbank bzw. zu dem Mapper. Mir wären diesbezüglich POCOs lieber.
    D.h. als Alternative konfiguriere per Code das Mapping von Eigenschaften zu Spalten, etc. Schau dir dazu als Inspiration das  Fluent Api von Entity Framework an.

  • Baue den String nicht einfach mit += zusammen. Auch wenn es vermutlich nur wenige String-Verkettung sein werden, ist ein StringBuilder passender.
    Außerdem hast du mit dem StringBuilder mehr Möglicheiten zum Bauen des Strings, daher auch sein Name.

  • Richtig schön wäre das umgesetzt durch Verwendung vom Builder-Pattern. Schau dir dies einmal an und versuche das so umzusetzen. Dadurch gewinnst du an Flexibilität, kannst das super (Unit-) Testen und bist auch offen für einfach Erweiterungen und Anpassungen.


Zitat:
Wie bereits aus meinen anderen Beiträgen ersichtlich beschäftige ich mich momentan

Nimm bitte nicht an, dass jeder potentielle Helfer weiß womit sich die Fragenstellenden beschäftigen ;-)


mfG Gü
08.06.2017 20:07 Beiträge des Benutzers | zu Buddylist hinzufügen
resper
myCSharp.de-Mitglied

Dabei seit: 15.02.2017
Beiträge: 33
Entwicklungsumgebung: Visual Studio
Herkunft: Kassel

Themenstarter Thema begonnen von resper

resper ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo gfoidl,

danke für die Anpassung des Titels und die Verschiebung ins richtige Forum.

Zu Punkt 2:
Ich habe das ganze mal mit einem StringBuilder umgesetzt, war es ungefähr das was du meintest:

C#-Code:
private void createTable<T>()
{
    PropertyInfo[] props = typeof(T).GetProperties();

    string[] cols = new string[props.Count()];

    for(int i = 0; i < props.Count(); i++)
    {
        StringBuilder colString = new StringBuilder(String.Format("'{0}'", props[i].Name));
        var attrs = props[i].GetCustomAttributes(true);
        foreach (DbAttributes attr in attrs)
        {
            if (attr.IsInteger) colString.Append(" INTEGER");
            if (attr.IsText) colString.Append(" TEXT");
            if (attr.IsPrimary) colString.Append(" PRIMARY KEY");
            if (attr.IsAuto) colString.Append(" AUTOINCREMENT");
        }
        cols[i] = colString.ToString();
    }

    string createTable = String.Format("CREATE TABLE IF NOT EXISTS '{0}' ({1});", typeof(T).Name, String.Join(", ", cols));
    queryNon(createTable);
}

Zu Punkt 1 und 3:
Da muss ich wohl noch etwas Zeit investieren. Da mein Englisch nicht sehr gut ist, brauche ich für solche etwas komplexeren Themen immer etwas länger, weil ich die Artikel in der Regel mehrfach lesen muss. Werde ich mich die nächsten Tage dran setzten.
09.06.2017 00:03 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Stefan.Haegele Stefan.Haegele ist männlich
myCSharp.de-Mitglied

avatar-3068.jpg


Dabei seit: 13.03.2009
Beiträge: 381
Entwicklungsumgebung: Visual Studio 2010 Ultimat
Herkunft: Untermeitingen


Stefan.Haegele ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Nur mal so als Idee (so mache ich das ganze):

Ich habe alle SQL Befehle in der (jeweiligen) Datenbank gespeichert und lade diese am Anfang in eine Dictionary. Im Programm gibt es nur SQL Befehle für:

-> Das Laden der SQl Befehle aus den jeweiligen Datenbanken

Somit muss ich die Befehle nicht mühsam zusammensatzen und greife per ID auf die jeweils korrekten SQL Befehle zu. (Und zur Laufzeit habe ich natürlich immer nur die SQL Befehle des aktuellen Provider geladen).

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Stefan.Haegele am 09.06.2017 07:53.

09.06.2017 07:52 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
gfoidl gfoidl ist männlich
myCSharp.de-Team

avatar-2894.jpg


Dabei seit: 07.06.2009
Beiträge: 6.651
Entwicklungsumgebung: VS 2019
Herkunft: Waidring


gfoidl ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo resper,

der StringBuilder gehört vor die for-Schleife, da mit dem der gesamte String gebaut werden soll.
Das erspart dann auch das string.Join.

Es sollte string createTable = myStringBuilder.ToString() sein.

mfG Gü
09.06.2017 09:12 Beiträge des Benutzers | zu Buddylist hinzufügen
resper
myCSharp.de-Mitglied

Dabei seit: 15.02.2017
Beiträge: 33
Entwicklungsumgebung: Visual Studio
Herkunft: Kassel

Themenstarter Thema begonnen von resper

resper ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat von gfoidl:
Das erspart dann auch das string.Join.

Das String.Join fand ich ganz praktisch wegen dem eingebauten Seperator

Zitat von FZelle:
Und ich würde das selbst implementieren komplett sein lassen, wenn es nicht der eigentliche Sinn ist das mit Attributen und Refelection zu lernen.

 SQLite-NET hat das alles schon implementiert incl. Schemaupdate und allem.

An dem Prinzip versuche ich mich zu orientieren. Aber so lerne ich am besten, wenn ich solche Funktionen nachbaue und versuche zu verstehen wie das funktioniert.

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von resper am 09.06.2017 19:51.

09.06.2017 19:49 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
FZelle
myCSharp.de-Poweruser/ Experte

Dabei seit: 23.04.2004
Beiträge: 9.839


FZelle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Und ich würde das selbst implementieren komplett sein lassen, wenn es nicht der eigentliche Sinn ist das mit Attributen und Refelection zu lernen.

 SQLite-NET hat das alles schon implementiert incl. Schemaupdate und allem.
09.06.2017 13:06 Beiträge des Benutzers | zu Buddylist hinzufügen
FZelle
myCSharp.de-Poweruser/ Experte

Dabei seit: 23.04.2004
Beiträge: 9.839


FZelle ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Zitat:
An dem Prinzip versuche ich mich zu orientieren. Aber so lerne ich am besten, wenn ich solche Funktionen nachbaue und versuche zu verstehen wie das funktioniert.

Halte ich nach 30 Jahren Softwareentwicklung für den Falschen Weg.
Erst die Grundlagen richtig lernen und dann ausprobieren geht deutlich schneller und ist weniger frustrierend als erst bisschen lesen, dann schon mal anfangen und dann ständig nachfragen Frickeln usw zu müssen.

Aber ist deine Zeit und deine Nerven.
10.06.2017 13:14 Beiträge des Benutzers | zu Buddylist hinzufügen
RED-BARON
myCSharp.de-Mitglied

Dabei seit: 22.05.2006
Beiträge: 74


RED-BARON ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

SQL-Befehl (String) aus Klasse und Attribute erstellen ist evtl. nur der erste Schritt. Im zweiten Schritt wird das bauen des Befehls mit der tatsächlichen
Struktur der Tabellen abgeglichen. So dass "alte" Clients mit neuer Datenstruktur genauso sinnvoll arbeiten können wie neue Clients mit alter Struktur.
Für unsere mobile App gilt genau diese Anforderung, da niemals es möglich sein kann, dass die zentrale Applikation und erst recht nicht die mobilen Geräte
gleichzeitig mit einem Update versorgt werden können.
Ich weiß nicht ob die aktuellen Frameworks oder Provider so etwas unterstützen. Zu Zeiten von Android 2.1 habe ich nichts passendes gefunden.
26.06.2017 22:32 Beiträge des Benutzers | zu Buddylist hinzufügen
Deaktiviertes Profil Deaktiviertes Profil ist männlich
myCSharp.de-Mitglied

Dabei seit: 06.07.2014
Beiträge: 985


Deaktiviertes Profil ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top


Eine mobile App sollte sich niemals direkt mit einer externen Datenbank verbinden. Darum gibt es das Problem dieser Art dort gar nicht.

Eine versionierte WebApi stellt die Funktionen auch für die alten Clients zur Verfügung.
26.06.2017 22:43 Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 2 Jahre.
Der letzte Beitrag ist älter als 2 Jahre.
Antwort erstellen


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 07.06.2020 11:23