Frage

Hier ist eine Vereinfachung meiner Datenbank:

Table: Property
Fields: ID, Address

Table: Quote
Fields: ID, PropertyID, BespokeQuoteFields...

Table: Job
Fields: ID, PropertyID, BespokeJobFields...

Dann haben wir noch andere Tabellen, die sich darauf beziehen Zitat Und Arbeit Tische einzeln.

Ich muss jetzt eine hinzufügen Nachricht Tabelle, in der Benutzer telefonische Nachrichten aufzeichnen können, die Kunden zu Jobs und Angeboten hinterlassen haben.

Ich könnte zwei identische Tabellen erstellen (QuoteMessage Und JobNachricht), aber das verstößt gegen das DRY-Prinzip und scheint chaotisch zu sein.

Ich könnte einen erstellen Nachricht Tisch:

Table: Message
Fields: ID, RelationID, RelationType, OtherFields...

Dies hält mich jedoch davon ab, Einschränkungen zu verwenden, um meine referenzielle Integrität durchzusetzen.Ich kann mir auch vorstellen, dass es später auf der Entwicklungsseite bei der Verwendung von Linq to SQL zu Problemen kommen wird.

Gibt es eine elegante Lösung für dieses Problem oder muss ich am Ende etwas zusammenhacken?

Verbrennungen

War es hilfreich?

Lösung

Erstellen Sie eine Nachrichtentabelle, die eine eindeutige MessageId und die verschiedenen Eigenschaften enthält, die Sie für eine Nachricht speichern müssen.

Table: Message
Fields: Id, TimeReceived, MessageDetails, WhateverElse...

Erstellen Sie zwei Linktabellen – QuoteMessage und JobMessage.Diese enthalten jeweils nur zwei Felder, Fremdschlüssel für das Angebot/den Auftrag und die Nachricht.

Table: QuoteMessage
Fields: QuoteId, MessageId

Table: JobMessage
Fields: JobId, MessageId

Auf diese Weise haben Sie die Dateneigenschaften einer Nachricht nur an einer Stelle definiert (was eine einfache Erweiterung und Abfrage über alle Nachrichten hinweg ermöglicht), aber Sie verfügen auch über die referenzielle Integrität, die Angebote und Jobs mit einer beliebigen Anzahl von Nachrichten verknüpft.Tatsächlich könnten sowohl ein Angebot als auch ein Job damit verknüpft sein Dasselbe Nachricht (Ich bin nicht sicher, ob das für Ihr Geschäftsmodell geeignet ist, aber das Datenmodell bietet Ihnen zumindest die Möglichkeit).

Andere Tipps

Die einzige andere Möglichkeit, die ich mir vorstellen kann, besteht darin, eine Basis-Nachrichtentabelle mit sowohl einer Id als auch einer TypeId zu haben.Ihre Untertabellen (QuoteMessage und JobMessage) verweisen dann sowohl auf MessageId als auch auf TypeId auf die Basistabelle – verfügen aber auch über CHECK CONSTRAINTS, um nur die entsprechende MessageTypeId zu erzwingen.

Table: Message
Fields: Id, MessageTypeId, Text, ...
Primary Key: Id, MessageTypeId
Unique: Id

Table: MessageType
Fields: Id, Name
Values: 1, "Quote" : 2, "Job"

Table: QuoteMessage
Fields: Id, MessageId, MessageTypeId, QuoteId
Constraints: MessageTypeId = 1
References: (MessageId, MessageTypeId) = (Message.Id, Message.MessageTypeId)
            QuoteId = Quote.QuoteId

Table: JobMessage
Fields: Id, MessageId, MessageTypeId, JobId
Constraints: MessageTypeId = 2
References: (MessageId, MessageTypeId) = (Message.Id, Message.MessageTypeId)
            JobId = Job.QuoteId

Was bringt Ihnen das im Vergleich zu nur einer JobMesssage- und QuoteMessage-Tabelle?Dadurch wird eine Nachricht zu einem erstklassigen Bürger, sodass Sie alle Nachrichten aus einer einzigen Tabelle lesen können.Im Gegenzug ist Ihr Abfragepfad von einer Nachricht bis zum relevanten Angebot oder Job nur noch eine Verbindung entfernt.Es hängt irgendwie von Ihrem App-Flow ab, ob das ein guter Kompromiss ist oder nicht.

Was zwei identische Tische betrifft, die gegen DRY verstoßen – ich würde mich nicht darauf einlassen.Beim DB-Design geht es weniger um DRY als vielmehr um Normalisierung.Wenn die beiden Dinge, die Sie modellieren, dieselben Attribute (Spalten) haben, aber tatsächlich unterschiedliche Dinge (Tabellen) sind, ist es sinnvoll, mehrere Tabellen mit ähnlichen Schemata zu haben.Viel besser als umgekehrt, wenn man verschiedene Dinge zusammenfügt.

@burns

Ians Antwort (+1) ist richtig [siehe Anmerkung].Verwendung einer Viele-zu-Viele-Tabelle QUOTEMESSAGE beitreten QUOTE Zu MESSAGE ist das korrekteste Modell, bleibt aber verwaist MESSAGE Aufzeichnungen.

Dies ist einer davon selten Fälle, in denen ein Auslöser verwendet werden kann.Es ist jedoch Vorsicht geboten, um sicherzustellen, dass dies der Fall ist MESSAGE Der Datensatz kann nicht mit a verknüpft werden QUOTE und ein JOB.

create trigger quotemessage_trg
on quotemessage
for delete
as
begin

delete 
from [message] 
where [message].[msg_id] in 
    (select [msg_id] from Deleted);

end

Hinweis für Ian: Ich glaube, es gibt einen Tippfehler in der Tabellendefinition für JobMessage, wo die Spalten sein sollten JobId, MessageId (?).Ich würde Ihr Zitat überarbeiten, aber es könnte ein paar Jahre dauern, bis ich diesen Ruf erlangt habe!

Warum nicht einfach die beiden Felder „QuoteId“ und „JobId“ in der Nachrichtentabelle haben?Oder muss sich eine Nachricht entweder auf ein Angebot oder einen Auftrag beziehen und nicht auf beides?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top