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 » Datenlisten immer nach gleichem Schema erstellen
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Datenlisten immer nach gleichem Schema erstellen

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
Jessimaus Jessimaus ist weiblich
myCSharp.de-Mitglied

Dabei seit: 06.03.2017
Beiträge: 6


Jessimaus ist offline

Datenlisten immer nach gleichem Schema erstellen

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

Hallo Leute,

habe gerade gesehen, dass man hier eigene Programme oder Teile davon zur 'Begutachtung' bzw. Diskussion vorstellen kann.
Ich benötige in unserem Projekt etliche Listen, so dass ich die immer nach dem gleichen Schema erstellen möchte.
Ich habe mich weitgehend an der Vorgehensweise im Doberenz orientiert.
Die unten beispielhaft angeführte Klasse LstArtikel würde ich dann als Basisklasse für DtoArtikel verwenden wollen,
die um die Bearbeitungsfunktionen Insert, Update und Delete erweitert ist.

Wie man schnell sieht, ist es nichts kompliziertes aber vielleicht gibt es ja den einen oder anderen hilfreichen Hinweis oder gar grundsätzliche Einwände.
Beispielsweise bin ich nicht sicher, ob das using nicht besser durch einen try/catch-Block ersetzt werden sollte.

Ich freue mich auf eure Kommentare
Liebe Grüße Jessimaus

C#-Code:
#region using-Anweisungen
    using System;
    using System.Collections.ObjectModel;
    using System.Data;
    using System.Data.SqlClient;
    using System.Globalization;
    using Model.POCO;
    using Model.POCO.Database;
#endregion
namespace ViewModel.Lists{
    public class LstArtikelstamm : Collection<Artikelstamm>{

        private readonly    SqlConnection _SqlCon;
        private readonly    int _MandantenID;
        private const string COMMANDTEXT =
            @"SELECT * FROM [dbo].[ilfSelectArtikelliste](@MandantenID)";

        public LstArtikelstamm(MdbConnection MdbCon){
            if(MdbCon == null) return;

            _SqlCon        = MdbCon.SqlCon;
            _MandantenID    = MdbCon.MandantenID;
            fill_Liste();
        }    // End Konstruktor

        private void fill_Liste(){
            using(var _SqlReaderCommand = POCOModelBase.get_SqlCommand()){
                if(_SqlReaderCommand == null) return;

                _SqlReaderCommand.Connection    = _SqlCon;
                var _DrPrmMandantenID = new SqlParameter("@MandantenID", SqlDbType.Int){
                    Direction = ParameterDirection.Input
                };
                _SqlReaderCommand.Parameters.Add(_DrPrmMandantenID);
                _SqlReaderCommand.CommandText = COMMANDTEXT;
                if(_SqlCon.State != ConnectionState.Open){
                    _SqlCon.Open();
                }
                Clear();
                _SqlReaderCommand.Parameters[0].Value = _MandantenID;
                using(var _Reader = _SqlReaderCommand.ExecuteReader(CommandBehavior.CloseConnection)){
                    if(!_Reader.HasRows) return;

                    while(_Reader.Read()){
                        var Listenartikel = new Artikelstamm{
                            MandantenID    = _MandantenID,
                            ArtikelID    = Convert.ToString(_Reader["ArtikelID"], CultureInfo.CurrentCulture),
                            Artikelname    = Convert.ToString(_Reader["Artikelname"], CultureInfo.CurrentCulture),
                            SteuersatzID    = Convert.ToInt32(_Reader["SteuersatzID"], CultureInfo.CurrentCulture),
                            KategorieID     = Convert.ToInt32(_Reader["KategorieID"], CultureInfo.CurrentCulture),
                            GruppenID    = Convert.ToInt32(_Reader["GruppenID"], CultureInfo.CurrentCulture),
                            Bearbeiter    = Convert.ToString(_Reader["Bearbeiter"], CultureInfo.CurrentCulture),
                            LetzteAenderung    = Convert.ToDateTime(_Reader["LetzteAenderung"], CultureInfo.CurrentCulture),
                            Zeilenversion    = _Reader.GetFieldValue<byte[]>(_Reader.GetOrdinal("Zeilenversion")),
                            Anzahl        = Convert.ToInt32(_Reader["Anzahl"], CultureInfo.CurrentCulture)
                        };
                        Add(Listenartikel);
                    }    // End While
                }    // End using - Reader
            }    // End Using - SQLCommand
        }    // End fill_Liste
    }    // End class
}    // End namespace
Neuer Beitrag 20.09.2017 10:22 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Jamikus Jamikus ist männlich
myCSharp.de-Mitglied

Dabei seit: 15.11.2012
Beiträge: 232
Entwicklungsumgebung: MS Visual
Herkunft: Oberhausen (NRW)


Jamikus ist offline

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

Hallöchen

Zitat von Jessimaus:
Beispielsweise bin ich nicht sicher, ob das using nicht besser durch einen try/catch-Block ersetzt werden sollte.

Also einen oder beide using gegen try/catch zu tauschen, wäre hier nicht gegeben. Objekt SQLCommand und SQLReader werden intialisiert und definitiv und sicher dispost, wenn sie nicht mehr gebraucht werden. Eine Verwendung die mehr als erwünscht ist.

Ein Problem, welches mir auffällt ist eher die SQL-Verbindung.
Du prüfst zwar richtig, ob die Verbindung offen ist mittels

C#-Code:
if(_SqlCon.State != ConnectionState.Open)
{
       _SqlCon.Open();
}

und öffnest sie notfalls.

1. Wenn du sie öffnest, wieso schließt du sie dann nicht?
2. Der sicherste Weg ist Eine sichere Methode wäre*: Eine Verbindung nur solange offen zu halten, solange sie verwendet wird. Leider ist nicht ganz erkenntlich woher die Verbindung kommt und wie lang ihre Lebensdauer schon besteht.

Vom Stil her würde ich den Select nicht als fest hartverdrahtetes Feld initialisieren.

Beim Konstruktor hätte ich wohl eher eine ArgumentNullException erwartet statt einfach nur ein "return", weil es wohl definitiv ein nicht gewünschtes Ergebnis ist, wenn der Parameter NULL ist.

*Kleine Korrektur nachdem ich mich des Wortes vergriffen habe und mir ein kleines Missgeschick durchgegangen ist.

Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Jamikus am 20.09.2017 14:27.

Neuer Beitrag 20.09.2017 13:47 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Abt
myCSharp.de-Team

avatar-4119.png


Dabei seit: 20.07.2008
Beiträge: 13.835
Herkunft: Stuttgart/Stockholm


Abt ist offline

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

Zitat von Jamikus:
Der sicherste Weg ist: Eine Verbindung nur solange offen zu halten, solange sie verwendet wird. Leider ist nicht ganz erkenntlich woher die Verbindung kommt und wie lang ihre Lebensdauer schon besteht.

Der sicherste Weg ist eigentlich ADO.NET das Pooling zu überlassen.
Dafür ist es da.
Neuer Beitrag 20.09.2017 14:03 Beiträge des Benutzers | zu Buddylist hinzufügen
T-Virus T-Virus ist männlich
myCSharp.de-Mitglied

Dabei seit: 17.04.2008
Beiträge: 1.518
Entwicklungsumgebung: Visual Studio, Codeblocks, Edi
Herkunft: Nordhausen, Nörten-Hardenberg


T-Virus ist online Füge T-Virus Deiner Kontaktliste hinzu

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

Mein Tipp wäre es erst einmal deinen Code sauber umzusetzen.
Wozu machst du eine Ableitung von Collection, wenn du scheinbar in deinem Code nichts davon implementierst.
Ebenfalls solltest du deinen Datenmodel Code von der Datenschicht trennen.
Hier solltest du dringend das Drei Schichten Modell umsetzen.

T-Virus
Neuer Beitrag 20.09.2017 14:37 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
pinki
myCSharp.de-Mitglied

avatar-4072.jpg


Dabei seit: 24.08.2008
Beiträge: 683
Herkunft: OWL


pinki ist offline

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

Zitat von T-Virus:
Wozu machst du eine Ableitung von Collection, wenn du scheinbar in deinem Code nichts davon implementierst.

Ganz unten wird die Add- und ziemlich mittig die Clear-Methode verwendet.
Neuer Beitrag 20.09.2017 15:04 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Jessimaus Jessimaus ist weiblich
myCSharp.de-Mitglied

Dabei seit: 06.03.2017
Beiträge: 6

Themenstarter Thema begonnen von Jessimaus

Jessimaus ist offline

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

Hallo Jamikus,

vielen Dank für Deine Hinweise.

Die SQL-Verbindung ist Bestandteil von MdbCon und die ist in der Regel geschlossen.
Die Prüfung auf NULL im Konstruktor könnte man in der Tat weglassen, weil, wenn dieses Teil NULL ist, dann stirbt die ganze Anwendung ab.
Ich hatte mal die 30-Tage Testversion vom Resharper drauf und der hat rumgemeckert von wegen 'possible System.NullReferenzExceprion'.

Geschlossen wird die SQL-Verbindung automatisch zusammen mit dem Reader, wegen CommandBehavior.CloseConnection.

Wegen der using mache ich mir Gedanken, was passiert, wenn innerhalb dieser Blöcke irgendwas schiefgeht. Dann fliegt mir bzw. dem
Benutzer eine unbehandelte Ausnahme um die Ohren. Vielleicht sollte man innerhalb der using-Blöcke ein try/catch einbauen? Oder außen herum?

@T-Virus
Ich brauche eine Liste/Collection vom Typ Artikelstamm, warum soll ich also nicht von Collection ableiten?

Mit

C#-Code:
var Artikelliste = new LstArtikelstamm(MdbCon);

baue ich mir die Liste, die ich ans DataGrid oder die Combobox binde. Einfacher geht's doch gar nicht, oder? Leite ich nicht von Collection ab,
sondern erstelle die Liste innerhalb einer einfachen Klasse, habe ich doch auch nichts anderes als die Liste aller Artikel.

Gruß Jessimaus
Neuer Beitrag 20.09.2017 15:47 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
p!lle
myCSharp.de-Mitglied

avatar-3556.jpg


Dabei seit: 22.02.2007
Beiträge: 1.032
Entwicklungsumgebung: Visual Studio (Community) 2019


p!lle ist offline

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

Zitat von Jessimaus:
Vielleicht sollte man innerhalb der using-Blöcke ein try/catch einbauen? Oder außen herum?

using und try/catch schließen sich nicht gegenseitig aus und haben auch per se überhaupt nichts miteinander gleich. Das eine kümmert sich um das Aufräumen von Ressourcen, das andere um die Fehlerbehandlung.
Neuer Beitrag 20.09.2017 15:57 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
T-Virus T-Virus ist männlich
myCSharp.de-Mitglied

Dabei seit: 17.04.2008
Beiträge: 1.518
Entwicklungsumgebung: Visual Studio, Codeblocks, Edi
Herkunft: Nordhausen, Nörten-Hardenberg


T-Virus ist online Füge T-Virus Deiner Kontaktliste hinzu

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

@pinki
Hatte ich leider übersehen, aber das Konzept ist aus meiner Sicht nicht sinnvoll.
Ableiten sollte man nur, wenn man die Methode überschrieben will.
In diesem Kontext würde ich das ganze Model und die Datenschicht trennen.
Solchen Code würde ich nie schreiben, da hier keine saubere Schichten Trennung herrscht und der Code jetzt schon ziemlich unleserlich ist.

@Jessimaus
Hier wäre es sinnvoll das Drei Schichten Modell zu fahren.
Dann brauchst du auch keine Ableitung von Collection, was ohne Neuimplemntierung der Methoden nicht zielführend ist.

Hier wäre es sinnvoller das Drei Schichten Modell umzusetzen.
Dann hast du deine Definitionsschicht in dem deine Klasse Artikelstamm ohne Methoden sondern rein aus Properties und Konstruktor besteht.

Darüber liegt dann die Datenschicht, in der deine Lese-/Schreibvorgänge gegen die DB liegen.
Hier hättest du dann z.B. eine ListArtikelstamm Methode, die dir einfach eine List<Artikelstamm> Liste gibt.

Über der Datenschicht liegt dann die Anwendungsschicht, die sowohl Business Logik als auch den Zugriff zur Datenschicht enthält.

So trennst du sauber deine Verantwortungen von deinen Datenmodell und den Datenspeicherung/-verarbeitung.
Aktuell wirfst du dort deinen Code in deine Klasse und gibst ihr dann auch noch Abhängigkeiten für die Datenbank.
Ebenfalls missbrauchst du eine Ableitung unnötig um eine Liste von Artikelstamm zu bekommen.
Solchen Code solltest du dringend überarbeiten.
Ich vermute mal, dass deine Artikelstamm Klasse sich dann auch um das Anlegen, Ändern, Löschen und auslesen aus der DB kümmert.
Dies würde dann aber auch bedeuten, dass deine gesamte Architektur schon in den Datenmodellen feste verdrahtungen zur DB hat.

T-Virus
Neuer Beitrag 20.09.2017 17:12 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.594
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist offline

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

T-Virus: Ich stimme dir hier voll zu!

Und für Jessimaus der passende Artikel dazu:  [Artikel] Drei-Schichten-Architektur
Neuer Beitrag 20.09.2017 17:53 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Taipi88 Taipi88 ist männlich
myCSharp.de-Mitglied

avatar-3220.jpg


Dabei seit: 02.02.2010
Beiträge: 1.006
Entwicklungsumgebung: VS 2010
Herkunft: Mainz


Taipi88 ist offline

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

Hi,

wenn es hier schon um Daten geht - möchte ich an dieser Stelle neben der bereits erwähnten 3-Schicht-Architektur noch auf folgende Patterns hinweisen:
a) UnitOfWorkPattern
b) RepositoryPattern

Speziell letztere sieht in deinem Fall sehr interessant aus.

Des Weiteren wären Bibliotheken wie z.B. "Dapper" noch sehr interessant um die SQL-Daten zu parsen...

LG
Neuer Beitrag 21.09.2017 07:00 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.594
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist offline

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

Da scheint etwas von der Architektur her generell nicht zu stimmen, denn es gibt ja anscheinend schon einen "Model.POCO" sowie "Model.POCO.Database"-Namensbereich. Ob dann noch mal ein weiterer SQL-Code zum Datenzugriff notwendig ist, bezweifle ich mal...
Neuer Beitrag 21.09.2017 09:09 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

Zitat von Jessimaus:
private const string COMMANDTEXT = @"SELECT * FROM [dbo].[ilfSelectArtikelliste](@MandantenID)";[/csharp]

Für viele nur eine Kleinigkeit - für mich im Code immer ein NoGo: SELECT *....
Neuer Beitrag 29.09.2017 06:22 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
LaTino LaTino ist männlich
myCSharp.de-Poweruser/ Experte

avatar-4122.png


Dabei seit: 03.04.2006
Beiträge: 2.993
Entwicklungsumgebung: Rider / VS2019 / VS Code
Herkunft: Thüringen


LaTino ist offline

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



Zitat von Stefan.Haegele:
Für viele nur eine Kleinigkeit - für mich im Code immer ein NoGo: SELECT *....

Code:
1:
SELECT * FROM (SELECT id, name, age FROM people) WHERE rownum <=100

"Immer" gibt es nicht.

LaTino
Neuer Beitrag 29.09.2017 07:18 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

Zitat von LaTino:
"Immer" gibt es nicht.

LaTino


Zwar ein wenig aus dem Zusammenhang gerissen, aber ich denke du weisst genau, was ich meinte... :-)
Neuer Beitrag 29.09.2017 07:21 E-Mail | 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. 06.06.2020 12:10