Laden...

OOP, wie Winform controls einbinden?

Erstellt von Kostas vor 18 Jahren Letzter Beitrag vor 18 Jahren 3.456 Views
K
Kostas Themenstarter:in
597 Beiträge seit 2005
vor 18 Jahren
OOP, wie Winform controls einbinden?

Hallo Zusammen,

OOP ist mein Lieblingsthema seit geraumer Zeit.
Ich versuche heraus zu finden wie ich in Zukunft
OOP in meinen Projekten mit VS2005 C# einsetzen kann.

Ich werde überwiegend Datenbankanwendungen
entwickeln, und wahrscheinlich den OR-Mapper NDO
verwenden. Als DB MS-SQL-Server 2005.

Ich habe mich durch diverse Bücher gekämpft und
soweit mir einen Überblick verschaffen können wie
Klassen gebildet werden und wie die Daten aus der DB
in der Klasse (ohne OR-Mapper) gelangen.

So wie ich es sehe, wird für die Datenbindung der Controls wie
TextBoxes, CheckBoxes und auch die Navigation u.s.w. von mir händisch
Code geschrieben. Ich kann also nicht eine TextBox bequem über
den Eigenschaften-Explorer die Bindung an ein Dataset herstellen.

Durch OOP hat mach ja bereit einen enorm höheren Programmieraufwand
wenn jetzt auch noch die controls für das GUI per Code gebunden werden
müssen, dann vergeht einem ja wirklich die Lust.

Mit der Hoffnung dass ich Unrecht habe, bin ich
auf Eure Meinung gespannt.

Gruß Kostas

3.728 Beiträge seit 2005
vor 18 Jahren
Datenbindung

Du hast völlig Recht: Alles in Objekte zu packen ist unnötig hoher Programmieraufwand!

Ich stelle mir gerade vor, die Adresstabelle unseres CRM Systems als Objekt mit Properties zu schreiben. Das wären 162 Properties! Außerdem wäre da noch die Geschwindigkeit und Skalierbarkeit anzumerken: Bei OR-Mapping kann man immer nur ganze Datensätze abrufen. Das belastet das Netzwerk und die Server! Folgende Abfrage ist bei OR-Mapping nicht möglich:

SELECT ABCClassification FROM Customer WHERE CustomerID=1

Die kleinste Mögliche Einheit wäre ein Customer-Objekt. Um das zu erzeugen und die Properties mit Daten zu füllen, ist aber folgender Code erforderlich:

SELECT * FROM Customers WHERE CustomerID=1

In meinem Fall wären das 161 Felder im Resultset, die übers Netzwerk gehen, um nicht gebraucht zu werden. Einige der Felder sind vom Typ ntext und enthalten größere Texte (Notizen zum Kunden etc.). Da kommen locker 1 bis 10 KB für den kompletten Kundendatensatz zusammen.

Hinzu kommt, dass Objekte recht starr sind. Summenbildung ist z.B. auch ein Problem. Um z.B. den Warenwert aller offenen Aufträge zu ermitteln bedarf es eigentlich nur einer kleinen SQL Abfrage:

SELECT SUM(NetTotal) AS SumNetTotal FROM Orders WHERE Completed=0

Bei OR-Mapping müssen erst sämtliche offenen Aufträge abgerufen werden (natürlich über SELECT * ...). Dann muss in einer Schleife die NetTotal-Property der einzelnen Order-Objekte zusammenaddiert werden.

Für skalierbare Geschäftsanwendungen halte ich OR-Mapping sogar für schädlich. Es ist zwar alles typsicher (was natürlich seinen Reiz hat) und auch Entwickler ohne Datenbank Know-How kommen gut klar, aber fast alles kommt aus dem Code Generator (weil ja niemand stumpfsinnig hunderte von Properties eintippen will). Das kann keiner mehr sinnvoll warten (außer alles zu löschen, ein paar Parameter des Code Generators zu ändern und alles neu erzeugen zu lassen).

Die Bindung der Controls ist aus meiner Sicht das geringste Problem. Mit ein bisschen Reflection kannst Du Dir eine Bindungsunterstützung für Objekte mit wenig Aufwand selbst bauen.

Hier ist ein Schulungsvideo zum Thema Reflection:
http://www.microsoft.com/germany/msdn/nettv/folge2.mspx

Um z.B. Zeichenprogrammen, Textverarbeitungen oder sowas zu programmieren sind Objektmodelle mit Properties und Collections ne feine Sache, aber nicht für Datenbankanwendungen.

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo Kostas,

du liegst völlig falsch: Man sollte alles in Objekte packen.

Den hohen Programmieraufwand reduziert man durch die Verwendung von Oberklassen. Wenn es keine keine Datenbindung der Controls wie TextBoxes, CheckBoxes gibt, dann schreib dir selber TextBoxes-, CheckBoxes- usw. Controls, die diese Datenbindung bieten. Den Aufwand hast du einmal und durch die Verwendung dieser Controls sparst zu viel Zeit.

Das gilt nicht nur für Datenbindung, sondern für alle Eigenschaften und Verhaltensweisen, die du so brauchst. Das gilt auch nicht nur für Controls, sondern auf für Forms. Auch hier kann man bestimmte Fensterarten (z.B. Suchfenster) schon weitgehend vorkonfektionieren.

Und es gilt nicht nur für's GUI, sondern auch für die Modellklassen. Ich habe z.B. in meinen kommerziellen C#-Projekten eine Oberklasse für Modellobjekte verwendet, die Funktionalität von ca. 5000 Code Zeilen auf sich vereint. Keine Frage, dass die einem quasi alles abgenomment hat, was das Handling von Modellobjekten anging. Die Modellklassen sind dann entsprechend kurz.

Man hat sicher einmaligen Aufwand, solche Infrastruktur zu schaffen, aber anschließend greift ja dann die Wiederverwendbarkeit.

herbivore

K
Kostas Themenstarter:in
597 Beiträge seit 2005
vor 18 Jahren

Hi Rainbird,

herzlichen Dank für Deine ausführliche Antwort.

Das ist eine völlig neue Sichtweise mit den OR-Mappern.
Ich habe Projekte die einigen hundert Tabellen und Felder
in einer DB verwalten.
Geschätzt einmal, benötige ich alle Felder einer Tabelle in etwa
10% aller selects. In der Regen immer nur eine Untermenge.
Das OR-Mapper das so nicht vorsehen verwundert mich doch
sehr. Ich gehe dennoch davon aus, das ein OR-Mapper zwei
unterschiedliche Klassen bilden kann, welche ihre Daten in
der gleichen Tabelle schreiben können.
Ich kann ja in dem entsprechenden XML-File die Zuordnung
zwischen Klassenfelder und Tabellenfelder bestimmen.

Diesen Mehraufwand für weitere Klassen habe ich bis jetzt
noch nicht berücksichtigt.

Eigentlich würde das bedeuten das Datenbankanwendungen
von OOP nicht sonderlich profitieren würden.

Dieses Thema ist wirklich recht interessant, und für mich
sehr Wertvoll.

Gruß Kostas

K
Kostas Themenstarter:in
597 Beiträge seit 2005
vor 18 Jahren

Hi herbivore,

herzlichen Dank für Deine ausführliche Antwort.

Bitte um Verzeihung wenn ich Deine Ausführung noch
nicht verstehe (...Anfänger eben 🙂 ).

Du schreibst, "dann schreib dir selber TextBoxes"
Nun, die Controls die mir zur Verfügung stehen bei VS2005
reihen erstmal aus. Diese Controls haben auch eine Eigenschaft
um das Control an einem DataSet zu binden. Da ich jedoch
eigene Klassen und Objekte habe, und eben kein DataSet,
ist das binden nur über code möglich und nicht zur Entwurfszeit
visuell möglich. Etwas zusammenklicken geht meist schneller
als code zu schreiben. Und die Wahrscheinlichkeit Fehler zu machen
sinkt auch.

Meinungen (siehe Rainbird).**){blue} Sicherlich hat jeder auf seine Sichtweise
Recht. Nicht nur für mich sonder sicherlich auch für viele andere
Leser wird es interessant.

Bitte tauscht Eure Meinungen aus.

Gruß Kostas

49.485 Beiträge seit 2005
vor 18 Jahren

Hallo Kostas,

Du schreibst, "dann schreib dir selber TextBoxes".

natürlich würde ich die bestehenden Controls - wenn möglich - als Oberklassen verwenden und sie nur um zusätzliche Funktionalität erweitern.

Nun, die Controls die mir zur Verfügung stehen bei VS2005 reihen erstmal aus.

Scheinbar ja nicht bzw. bieten sie scheinbar nicht genug Funktionialität. 🙂

Diese Controls haben auch eine Eigenschaft um das Control an einem DataSet zu binden. Da ich jedoch eigene Klassen und Objekte habe, und eben kein DataSet, ist das binden nur über code möglich und nicht zur Entwurfszeit visuell möglich.

Was ich meinte, ist die Controls quasi um Objectbinding zu erweitern. Wenn man es entsprechend macht, ist das dann auch zur Entwurfszeit visuell möglich.

Etwas zusammenklicken geht meist schneller als code zu schreiben. Und die Wahrscheinlichkeit Fehler zu machen sinkt auch.

Naja, das sehe ich nun genau andersherum. Ich benutze deshalb auch kein VS. Aber mein Vorschlag würde m.E. dein Zusammenklicken nicht behindern.

herbivore

K
Kostas Themenstarter:in
597 Beiträge seit 2005
vor 18 Jahren

... wenn sich die gleiche Frage noch jemand stellt:

Unter VS2005 ist es möglich die Contorls nicht nur an ein DataSet
zu binden sonder auch an Objekte, das war mich nicht klar.
Der folgende Link beschreibt es sehr gut.

http://www.microsoft.com/germany/msdn/library/visualtools/visualstudio2005/BenutzerdefinierteDatenbindungInWindowsForms20.mspx

F
10.010 Beiträge seit 2004
vor 18 Jahren

Und bei codeproject gibt es einen Artikel, der zwar nicht nach meinem Geschmack
ist, aber die grundlagen auch ziemlich einleuchtend erklärt.

http://www.codeproject.com/dotnet/AdoNetForOopPart2.asp

S
8.746 Beiträge seit 2005
vor 18 Jahren

Original von Kostas
Eigentlich würde das bedeuten das Datenbankanwendungen
von OOP nicht sonderlich profitieren würden.

Andersrum wird ein Schuh draus. Relationale DB unterstützen keine Objektorientierung (OO-Datenbanken tun das...). Und: ADO.NET ist eine Architektur, die relationale Konzepte umsetzt, aber eben - wie schon geschrieben - einigermaßen mit Objekten klar kommt.

Noch ein Tip zu O/R-Mappern: Nimm einen, der server-seitige Queries unterstützt. Ansonsten bist du ständig auf Client-Seite am Navigieren, was sich recht schlecht auf die Performance auswirkt.

K
Kostas Themenstarter:in
597 Beiträge seit 2005
vor 18 Jahren

Hallo Zusammen,

wir habe darüber diskutiert das wenn ein Artikel-Datensatz aus mehreren
Feldern bestächt, wobei auch Bilder, RTF u.s.w. enthalten sind, die OR-Mapper
nicht wirtschaftlich damit umgehen können weil im Objekt der komplette
Artikel-Datensatz gehalten wird. Auch wenn nur eine Untermenge der Felder
fallweise benötigt werden.

Ich habe heute erfahren das der NDO-Mapper mehrere Klassen auf die
gleich Tabelle mappen kann, wobei jede Klasse unterschiedliche Felder
enthalten kann. Ich kann also eine Klasse "Artikel_Stamm" mit allen
Felder für die Pflege des Artikels im Artikelstamm erzeugen, und eine weitere
Klasse "Artikel_Auftrag". Diese Klasse könnte z.b. nur fünf Felder beinhalten
eben genau diese die im Auftrag benötigt werden.

So empfiehlt es übrigens der Hersteller von NDO.
In diesem Ansatz finde ich mich wieder. So Arbeite ich jetzt aktuell mit
Querys. Ich hole mir nur genau diese Informationen die ich gerade benötige.

Nur weis ich nicht ob unter Anwendung von OOP etwas dagegen spricht.
Ich sehe eigentlich nur den Zustand das ein Objekt zerrissen wird.
Könnte das an anderer Stelle ein Nachteil sein?

Gruß Kostas

I
1.739 Beiträge seit 2005
vor 18 Jahren

Nur weis ich nicht ob unter Anwendung von OOP etwas dagegen spricht.

Nein, aus OOP-Sicht, spricht nichts dagegen. Im Fall das unterschiedliche Objekte aus der selben DB-Entität gleichzeitig im Speicher sind, sprechen höchstens Performanz und Speicherbedarf dagegen.

Ich sehe eigentlich nur den Zustand das ein Objekt zerrissen wird.

Welches? Meinst du damit: von einem Datensatzsatz werden nicht alle Felder geladen(das ist allg. so Usus mit oder ohne OOP)?
Wenn dein Objekt alle Eigenschaften hat die braucht ok, die DB ist nur die Ablage.

K
Kostas Themenstarter:in
597 Beiträge seit 2005
vor 18 Jahren

Hi ikaros,

die erste Antwort zu meiner Frage kam von Rainbird den ich sehr schätze,

Folgende Abfrage ist bei OR-Mapping nicht möglich:

   
SELECT ABCClassification FROM Customer WHERE CustomerID=1  
  

Sicherlich hat er Recht. Aber ist es notwendig wenn ich zwei
Klassen auf ein Tabelle mappen kann?

Gruß Kostas

I
1.739 Beiträge seit 2005
vor 18 Jahren

?

K
Kostas Themenstarter:in
597 Beiträge seit 2005
vor 18 Jahren

Original von ikaros
Welches? Meinst du damit: von einem Datensatzsatz werden nicht alle Felder geladen(das ist allg. so Usus mit oder ohne OOP)?
Wenn dein Objekt alle Eigenschaften hat die braucht ok, die DB ist nur die Ablage.

ich meine ein Artikel als Object hat nun mal in meinem Fall ca. 170 Felder
sie beschreiben den Artikel als ganzes. Ich verstehe noch nichts von OOP
aber ich habe immer wieder gelesen, man sollte Objekte so anlegen wie sie in
der Natur vorkommen. Aus diesem Grundsatz gehe ich davon aus, das eine
Object immer sein Ding komplett beschreibt.
Möglicherweise gilt dieser Grundsatz nicht immer oder ich habe es wieder mal
falsch interpretiert.

Gruß Kostas

I
1.739 Beiträge seit 2005
vor 18 Jahren

Achso.

Ein DB-Tupel enthält alle Daten die zum Artikel zugehörig sind(inkl FKs zu zus. Informationen). zB sind das 170 oder mehr Felder.
Nun Benötigst du nur Informationen von 3 oder x Feldern. Die Klasse nennt sich zum Bsp. ArtikelShortInfo und dient zur Information des Users, um Artikel zu erkennen und zuzuweisen(zu einer Bestellung etc). Es ist nicht notwendig alles zu laden und evtl. auch anzuzeigen. Hat die Klasse alle Informationen um ihren Job zu erledigen ist es genug. Den Artikeldatensatz mit all seinen Eigenschaften würde ich nicht als Klasse sehen, er ist der Speicherort für einen Artikel, er muss keiner Klasse entsprechen. Geht es darum einzelne Artikel zu Verwalten(Anzeigen, ändern, speichern, löschen(naja)) brauchts wahrscheinlich mehr Properties. Es aber auch durchaus möglich(wenn sinnvoll), den Artikel - DS in mehrere Klassen zu splitten.
Das (relationale) Modell der Datenbank 1 : 1 in Klassen zu mappen ist jedenfalls selten sinnvoll.

Ob es überhaupt sinnvoll ist relationale Daten auf Klassen abzubilden, da haben schon Herbivore und Rainbird gegensätzliche Statements abgegeben. Darauf gehe ich hier nicht weiter ein(Ich sehe das Applikationsabhängig).

Fakt ist: eine Klasse/oder Datenmenge muss nicht jede Information beinhalten die vorhanden ist. Nur die, für die Verarbeitung notwendigen. Es gibt, um es nochmals zu wiederholen keinen Widerspruch, zu OOP.

BTW.
Man kann Klassen auch "on the fly" via Reflection aus dem Resultset einer Abfrage erstellen. Die Methode zum Speichern kann natürlich sehr komplex werden(join über 10 Tabellen, und dann die Schemadaten zusammenpusseln).
Besser ist natürlich ein leistungsfähiger und einfach verständlicher Mapper.

K
Kostas Themenstarter:in
597 Beiträge seit 2005
vor 18 Jahren

Danke ikaros,

jetzt hab auch ich es verstanden 🙂

Zu einer anderen Sache: (zur Laufzeit generierter Select für das suches geht das?)

Ich habe meist ein eigenes Form zum Suchen.
z.B.: AuftragSuchenForm. Auf diesem Form habe ich eine Menge an Text-
Feldern, Checkboxes u.s.w. welche nicht mit den Daten gebunden sind.
Der Anwender kann als in die Suchfelder Firma etwas eingeben.
Wenn die Suche gestartet wird, gehe ich alle Controls durch und baue mir
dynamisch das sql Statement zusammen. Je nach dem kommt dabei
von einem Select über eine Tabelle bis hin zu joinigs über mehrere Tabelle
zusammen. Da SQL einfach nur ein String ist, ist es kein Problem so etwas zu
machen. Wie sieht es da aus mit OR-Mappern. Ist es auch da möglich zur Laufzeit
die Select Bedingung dynamisch zu erzeugen?

Gruß Kostas

I
1.739 Beiträge seit 2005
vor 18 Jahren

Ist es auch da möglich zur Laufzeit die Select Bedingung dynamisch zu erzeugen?

Soviel ich weiss, nur wenn die Where-Klausel beinflusst wird(irgendwie logisch). Ansonsten kann ich noch meine Meinung zum "zusammenschrauben" von SQL-Anweisungen abgeben(insbesondere im zusammenhang mit Textboxen): Gefährlich(SQL - Injection), besser du arbeitest mit Parametern.

Edit:
http://de.wikipedia.org/wiki/SQL-Injektion

4.506 Beiträge seit 2004
vor 18 Jahren

Hallo zusammen,

ein dynamisches zusammenbauen des SQL-Statements ist auch über Parameter möglich. Dann aber wirklich nur über Reflection und einem Switch-Statement, der dann den Typ des jeweiligen Datenfeldes überprüfen muss, aber ob das wirklich der Aufwand wert ist? Von Performance mal abgesehen. Ich glaube ich würde eine Mischform anstreben.

Für jedes SQL-Statement bei denen 'alle' Felder gebraucht werden, wie z.B. bei einem Insert, dort würde ich die SQL-Statements mir einmal bei der Objektinstanziierung einen String zusammenbasteln, um diesen dann wieder verwenden zu können (also nur einmal zusammenbasteln).

Andere Abfragen, die nur einen Teil der Felder benötigen, würde ich on-the-fly erstellen lassen, wie gesagt über Reflection und unbedingt mit Parametern.

Was ich noch ergänzend sagen wollte, ist dass hier noch gar nicht die Sortierung angesprochen wurde. Ich behaupte, dass wenn ich meine Daten so von der DB abrufe, dass sie schon so sortiert ist, wie ich es brauche, dass das performanter ist, als wenn ich zunächst die Daten hole, und dann anfange im Code sortieren zu lassen (teilweise nicht vermeidbar, wenn der Benutzer die Sortierung verstellt).

Deshalb würde ich auch beim DB-Objekt Mapping (in welcher Form auch immer) auch schon eine dynamische Sortierung (konkret eine Order-Klausel) vorsehen.

Ciao
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

S
8.746 Beiträge seit 2005
vor 18 Jahren

Original von Kostas
Ich habe heute erfahren das der NDO-Mapper mehrere Klassen auf die
gleich Tabelle mappen kann, wobei jede Klasse unterschiedliche Felder
enthalten kann. Ich kann also eine Klasse "Artikel_Stamm" mit allen
Felder für die Pflege des Artikels im Artikelstamm erzeugen, und eine weitere
Klasse "Artikel_Auftrag". Diese Klasse könnte z.b. nur fünf Felder beinhalten
eben genau diese die im Auftrag benötigt werden.

Ehrlich gesagt riecht das für mich danach, dass deine relationales Datenmodell nicht ausreichend normalisiert ist (170 Felder sind gigantisch). Artikel-Stamm und -Auftrag wären eigentlich schon in einem relationalen Modell zwei Tabellen (und damit auch zwei Klassen). Wenn ein ER-Modell richtig modelliert ist, hast du solche Aufteilungprobleme praktisch nicht (im Gegenteil, siehe unten).

In einem "guten" Datenmodell liefert jede Tabelle nur die relevanten Information einer in sich konstistenten aber zugleich minimalen Entität zurück.

Normalerweise hat ein OR-Mapper eher die umgekehrte Aufgabe als das "in zwei Klassen abbilden" bei dir: Nämlich aus einem starkt zerlegten OR-Modell gemeinsame Klasse zu bilden (Composite). So werden aus Tabellen Vererbungshierarchien und eben das Kompositum. Der OR-Mapper muss es in solchen Fällen erlauben, das Prefetching eingebetteter Objekt zu steuern (also auszublenden).

K
Kostas Themenstarter:in
597 Beiträge seit 2005
vor 18 Jahren

Original von svenson

Ehrlich gesagt riecht das für mich danach, dass deine relationales Datenmodell nicht ausreichend normalisiert ist (170 Felder sind gigantisch). Artikel-Stamm und -Auftrag wären eigentlich schon in einem relationalen Modell zwei Tabellen (und damit auch zwei Klassen). Wenn ein ER-Modell richtig modelliert ist, hast du solche Aufteilungprobleme praktisch nicht (im Gegenteil, siehe unten).
auszublenden).

oh, das habe ich unbedingt. Artikel und Auftrag sind selbst verständlich zwei
Tabellen. Die 170 Felder stehen im Verhältnis 1:1 zur ArtikelID(PK) der Tabelle
Artikel.
Ich habe eine Tabelle AuftragKopf und eine AuftragDetail 1:n
Um ein Artikel in AuftragDetail aufzunehmen, benötige ich ein Select auf
fünf Artikelfelder. Sobald der Anwender den Artikel lokalisiert hat, werden
die Informationen in AuftragDetail kopiert. Kopiert deshalb, weil der
Anwender die Feldinhalte nachträglich verändern könne haben möchte.
Was der Anwender jedoch nicht verändern kann ist, die ArtikelID die ich
ebenfalls in AuftragDetail mitnehme.

Gruß Kostas