Ich weiß wirklich nicht, was ich in den Titel schreiben soll, also lies nicht zu viel hinein.Gibt es einen besseren Weg (C#)?
Wie auch immer, um zu erklären, mit was ich Probleme habe, ist dies. Ich habe drei Klassen: A, B und C. Die Klassenhierarchie ist, wie folgt:
< A - B < - C
(. So A ist die Basisklasse)
Die Anwendung In Frage steht eine Datenbank App. Es fragt Informationen mehrere Tabellen ab (A ist eine Tabelle, und B und C sind eins) und speichert es in einer Instanz von C. Dieser Teil funktioniert gut. Das Problem ist, wenn ich die durch B und C vertretene Tabelle aktualisieren möchte.
Um Standardcode für jeden Code zu vermeiden, verwende ich Reflektion, um eine Aktualisierungsabfrage von der Klasse zu generieren. Wenn ich jedoch eine Instanz einer C-Klasse übergebe, bedeutet dies, dass sie auch alle Elemente aus A auswählen wird, was eine separate Tabelle ist. Daher wird die Aktualisierungsabfrage falsch sein. Und da liegt mein Problem. I wollen alle Mitglieder von B und C ohne viel Code und mit einer sauberen, skalierbaren Lösung zu schreiben. Ich weiß einfach nicht wie.
(Ich verwende derzeit einen Ansatz, bei dem ich alle Mitglieder des Top-Level-Typs auswählen, dann alle Eltern der Klasse durchsuchen und alle diese Mitglieder auswählen und Mitglieder nicht mehr sammeln, wenn sie einen bestimmten Elterntyp findet, z ist eine schreckliche Lösung, denke ich.)
Alle diese Klassen enthält Variablen abgerufen aus der Datenbank und haben keine Methoden oder Felder. Irgendwelche guten Ideen, wie man dieses Problem angeht? Ich habe gehört, dass C# keine Mehrfachvererbung hat, ein Tool, das perfekt für diesen Job ist (danke C#!).
Ich hoffe, ich mache mich klar.
EDIT1: Um einige Fragen zu beantworten und zusätzlichen Kontext zu geben. Zunächst einmal, so sieht mein System heute aus. Um Daten abzufragen, habe ich zuerst eine Klasse X und einen Abfragetext. Die Abfrage wird für die Datenbank ausgeführt und gibt einige Zeilen zurück. Dann wird jede Zeile in eine Instanz von X konvertiert und zu einer Liste hinzugefügt. Der Code weiß, wie eine Zeile in ein X konvertiert wird, indem eine Reflektion verwendet wird und die tatsächlichen Variablen in X und der Name der Spalten in der abgerufenen Datenbankzeile betrachtet werden. Es nimmt dann die Spalte A und speichert diese Information in der Variablen A in X. Indem Sie also eine Klasse X erstellen und diese mit der Datenbankstruktur abgleichen, brauchen Sie nur eine weitere Tabelle mit Daten zu holen.
Manchmal müssen Sie Daten aus mehreren Tabellen abrufen und zusammenstellen. Um dies zu tun, brauche ich eine Klasse X, die mit den Informationen aus der Abfrage übereinstimmt. Es gibt viele Daten, die ich abrufe, und alle diese Daten haben eine gemeinsame Teilmenge, die aus Tabelle A abgerufen wurde. Der Rest wird von vielen anderen Tabellen abgerufen, die zusätzliche Daten enthalten. Daher sieht das Typsystem immer wie etwas A < - B aus, wobei A die gemeinsame Teilmenge aller von mir abgerufenen Daten ist. Dies funktioniert hervorragend für Abfragen. Ich kann zusätzliche Daten und eine Klasse hinzufügen und ich bin fertig. Kein Kesselblechcode mehr.
Aber das ist nur die halbe Geschichte. Ich muss diese Tabellen auch aktualisieren (ich brauche A nicht zu aktualisieren). Aber um das zu tun, muss ich die Daten trennen, die von der Tabelle A, der gemeinsamen Teilmenge, geholt werden. Hier ist, wie ich die Aktualisierung mache:
Connection.RunUpdateQuery (..., Utility.ToDictionary (Entry));
Dabei ist Entry die Klasse, die die Informationen enthält, die in der Zieltabelle aktualisiert werden sollen.Also konvertiere ich die Klasse in ein Dictionary, das den Spaltennamen und den Spaltenwert darstellt, und sende das RunUpdateQuery, das eine sql-Aktualisierungsanweisung generiert und an die Datenbank sendet. Auch das ist wirklich nett, da ich absolut keinen Boilerplate-Code schreiben muss.
Aber Utility.ToDicionary kann nicht wissen, welche Teilmenge von Informationen ich eigentlich einfügen möchte. Es nimmt einfach jede Variable in der Klasse und wandelt sie in ein Wörterbuch um, wobei der Name der Variablen der Spaltenname (d. H. Der Schlüssel des Wörterbuchs) ist. Wenn ich in diesem Fall ein C übergebe, möchte ich eigentlich nur B und C, weil sie Teil der Zieltabelle sind, die ich aktualisieren möchte. Die A-Teilmenge ist Teil einer anderen Tabelle, die ich nicht aktualisieren möchte.
Wenn es ein Framework gibt, das all diese Arbeit macht, bin ich dafür. Aber momentan habe ich nicht die Zeit, diesen Code neu zu schreiben. Also muss ich damit bis später warten.
Dies ist auch meine eigene Datenbank, die ich entwerfe. Ich bin für alles verantwortlich, was das Design des Projekts betrifft.
Ich möchte wirklich keine Abfragen generieren, auch wenn es nur bedeutet, ein Tool auszuführen, denn a) es bedeutet mehr Arbeit bei jeder Datenbankänderung und b) es bedeutet mehr Bugs, weil ich vergessen könnte, bestimmte Orte zu aktualisieren etwas ändert sich. Mit meiner aktuellen reflexionsbasierten Lösung muss ich nichts ändern. Ich muss nur die Datenbank und eine geeignete Klasse entwerfen (was ich sowieso tun muss, da ich die Zeilen aus der Datenbank in geeignete erstklassige Bürger im Code übersetzen muss, damit ich leichter mit ihnen arbeiten kann).
Die Verwendung von Attributen scheint keine gute Methode zu sein, weil es alles kontextabhängig ist. Der Aufrufer, der eine Tabelle aktualisieren möchte, muss auswählen können, welche Felder in der Datenbank aktualisiert werden sollen, jedoch nicht auf solch einer feinkörnigen Ebene. Der Aufrufer sollte einfach in der Lage sein, die zu aktualisierende Klasse sozusagen auszuwählen.
Vielleicht gibt dies einige Klarheit in meinem Problem.
EDIT2: Beispiele der Klasse A, B, C:
C:
public class PumpEntry: SignalEntryD
{
public uint? Addr;
public uint MasterlistIdx;
public bool MinDominant;
public uint? TriggerInterval;
public uint? SpDef;
public uint? MinDef;
public uint? MaxDef;
public uint? Step0Def;
public uint? Step1Def;
public uint? Step2Def;
public uint? Step3Def;
public uint? Step4Def;
public uint? Step5Def;
public uint? ExReqFacBACNet, ExSpFacBACNet;
public decimal? DeltaTX0Def, DeltaTX1Def, DeltaTX2Def, DeltaTX3Def;
public uint? DeltaTYMinDef, DeltaTY0Def, DeltaTY1Def;
public string DeltaTSensor1, DeltaTSensor2;
public int? ReqLimitMethodDef;
}
B:
public class SignalEntryD: DeviceEntry
{
public int? Channel;
public int? pCOeNum;
}
A:
public class DeviceEntry: DbType
{
public int Id;
public DeviceType Type;
public string Name;
public string CMCategory;
public bool Generate;
public new string ToString() { return Name; }
}
'Ich höre C# hat keine Mehrfachvererbung, ein Werkzeug perfekt für diesen Job" Sie können stattdessen "Schnittstelle" verwenden. Eine Klasse kann mehrere Schnittstellen implementieren. –
Sie möchten Mitglieder der Klasse 'C' bekommen, die nicht von Klasse' A' oder 'B' geerbt wurden? –
Meiner Meinung nach ist der direkte Umgang mit Datenbanken in Ihrem Fall keine gute Lösung. Verwenden Sie ein ORM wie Entity Framework oder NHibernate. –