SQL Datenbankdesign - Best Practice

DrCox1911

Lt. Junior Grade
Registriert
Juni 2018
Beiträge
507
Nabend zusammen,

ich entwickle gerade eine Software, in der es vorab einiger Stammdaten benötigt. Mit diesen Stammdaten kann der User dann bestimmte Einträge erfassen.

Ein Teil dieser Stammdaten ist ein Material, das drei Verbauzustände hat und demnach drei Kosten.
Der Material und die Kosten werden werden später automatisch vorausgewählt, der User kann diese Auswahl aber überdefinieren.

Ich bin mir gerade unschlüssig, wie ich das ganze bei der Stammdateneingabe lösen soll.
Aktuell geistert mir folgender Aufbau durch den Kopf (pseudo-C#-Code):
C#:
public class Material
{
    public Guid MaterialId { get; set; }
    public Guid CostRawId { get; set; }
    public Guid CostWeldId { get; set; }
    public Guid CostCompleteId { get; set; }
    public string MaterialName { get; set; }
    public string MaterialNumber { get; set; }
    
    public Cost CostRaw { get; set; }
    public Cost CostWeld { get; set; }
    public Cost CostComplete { get; set; }
}
C#:
public class Cost
{
    public Guid CostId { get; set; }
    public Guid MaterialId { get; set; }
    public decimal CostValue { get; set; }
    public decimal ProgressMin { get; set; }
    public decimal ProgressMax { get; set; }
}

Nun will ich in meiner Blazor-UI allerdings das Anlegen eines neuen Produkts in einem Schritt machen, also direkt beides anlegen.
Mein Problem dabei: Cost hat ja auch einen ID-Verweis auf Material, das hat aber wiederum einen Verweis auf CostId. Zum Zeitpunkt meiner Eingabe existiert aber weder das eine noch das andere.

Das eigentliche Datenbankhandling macht EF Core.
Hoffe, dass mein Problem soweit klar ist. Wie würdet ihr denn die Sache angehen?
 
Bezogen aufs Datenbankesign: So wenig dopplungen in der Datenbank wie moeglich. Normalerweise normalisiert man das Schema nach der 3. Normalform
https://de.wikipedia.org/wiki/Normalisierung_(Datenbank)#:~:text=Unter Normalisierung eines relationalen Datenschemas,die keine Redundanzen mehr enthält.
https://www.datenbanken-verstehen.de/datenmodellierung/normalisierung/dritte-normalform/

Sollte dir fuer einen Ueberblick reichen.

Zum Pseudocode muss hier jemand anderes was sagen, aber die Struktur entsteht i.d.r anhand des Datenbank Schemas, was du als ER-Diagramm abbilden kannst (Datenbank Design Pseudocode)
https://de.wikipedia.org/wiki/Entity-Relationship-Modell
 
  • Gefällt mir
Reaktionen: Raijin, abcddcba und Vasdada
Wie madmax2010 schreib,
nimm die Normalform 3! Viele nutzen nur 2...., aber wenn du von 0 beginnst, immer normalform 3 nutzen.
 
  • Gefällt mir
Reaktionen: madmax2010
Kleine Anmerkung noch. Es gibt schoenere Darstellungen von Datenbank Schema resp. Tabellen, C# waere nicht meine erste Wahl um ueber die Modellierung nachzudenken. Aber ok, wenn es zweckmaessig ist, dann wohl auch in Ordnung. Nur wegen "Best Practice" als Buzzword mal erwaehnt
 
Prinzipiell sind die Verweise auf die Normalformen ein guter Anfang. Wenn du dich damit noch nie beschäftigt hast würde ich dir empfehlen dich erstmal dort einzuarbeiten.

Bezüglich dees konkreten Beispiels würde ich aus Material alle Verweise auf Cost entfernen und die Art der Kosten über eine entsprechende Typ-Eigenschaft abbilden. Spätere Erweiterungen (neue Kostentypen, Zeiträume in Kosten etc.) kannst du dadurch vergleichsweise einfach umsetzen. Ein Unique Index auf Cost (MaterialD, Type) verhindert die mehrfache Anlage gleichartiger Datensätze

C#:
public class Material
{
    public Guid MaterialId { get; set; }
    public string MaterialName { get; set; }
    public string MaterialNumber { get; set; }
}  

public class Cost
{
    public Guid CostId { get; set; }
    public Guid MaterialId { get; set; }
    public int Type { get; set; } // Bspw. 1 = Raw, 2 = Weld, 3 = Complete, kann auch über Enum abgebildet werden
    public decimal CostValue { get; set; }
    public decimal ProgressMin { get; set; }
    public decimal ProgressMax { get; set; }
}
 
  • Gefällt mir
Reaktionen: DrCox1911
Perfekt, danke euch. Stand wohl irgendwie auf dem Schlauch, denn genau so wie @Methumpen Vorschlag habe ich es in einer anderen Tabelle bereits umgesetzt.
 
Ringbezug = ganz schlecht. Normalerweise schon per informeller Beschreibung.

Kosten haben mit Material nichts zu tun. Keine Möglichkeit, zweiteres aus Ersterem abzuleiten: 2 Euro 99, welches Material? Keine Ahnung und auch nicht bestimmbar.

Ergo: keine Material Id bei den Kosten.

Schon vor best practices kommt eine gerichtete Struktur (cf ER Modell). Dazu überlegen, was hab ich, was will ich, und wie verhält sich das Ganze quantitativ zueinander?
Ggfs Tutorials angucken zu Datenbankdesign.
 
  • Gefällt mir
Reaktionen: BeBur und Raijin
RalphS schrieb:
Ringbezug = ganz schlecht. Normalerweise schon per informeller Beschreibung.
Da er von C# und Blazor schreibt, nehme ich mal an, es wird EF verwendet, wahrscheinlich code first.
Das setzt die IDs automatisch nur einmal dort wo es sinnvoll ist, die andere Referenz ist dann nur im Code vorhanden. Nennt sich "navigation property".
In der nun gefundenen Lösung kann er in Material noch ein
Code:
public List<Cost> Costs { get; set; }
hinzufügen, ohne dass das die Datenbankrelationen/-spalten verändert. Das nur zur Vervollständigung, warum man bei EF-Apps oft diese augenscheinlichen Ringbezüge sieht.
 
  • Gefällt mir
Reaktionen: Dalek
Zurück
Oben