3

これが私のデータベースの単純化です:

表: プロパティ
フィールド: ID、住所

表: 見積もり
フィールド: ID、PropertyID、BespokeQuoteFields...

表: ジョブ
フィールド: ID、PropertyID、BespokeJobFields...

次に、QuoteテーブルとJobテーブルに個別に関連する他のテーブルがあります。

ここで、ジョブと見積もりに関して顧客が残した電話メッセージをユーザーが記録できるメッセージテーブルを追加する必要があります。

2 つの同一のテーブル ( QuoteMessageJobMessage ) を作成することもできますが、これは DRY プリンシパルに違反しており、面倒です。

Messageテーブルを 1 つ作成できます。

表: メッセージ
フィールド: ID、RelationID、RelationType、OtherFields...

しかし、これにより、制約を使用して参照整合性を強制することができなくなります。また、後で Linq to SQL を使用して開発側で問題が発生することも予測できます。

この問題に対するエレガントな解決策はありますか、それとも最終的に何かを一緒にハックする必要がありますか?

火傷

4

4 に答える 4

4

一意の MessageId と、メッセージ用に保存する必要があるさまざまなプロパティを含む 1 つのメッセージ テーブルを作成します。

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

QuoteMessage と JobMessage の 2 つのリンク テーブルを作成します。これらには、Quote/Job と Message への外部キーの 2 つのフィールドだけが含まれます。

Table: QuoteMessage
Fields: QuoteId, MessageId

Table: JobMessage
Fields: JobId, MessageId

このようにして、Message のデータ プロパティを 1 か所だけで定義しましたが (拡張が容易になり、すべてのメッセージにクエリを実行できます)、Quotes と Jobs を任意の数のメッセージにリンクする参照整合性も得られます。実際、Quote と Job の両方を同じメッセージにリンクすることもできます (それがビジネス モデルに適しているかどうかはわかりませんが、少なくともデータ モデルには選択肢があります)。

于 2008-08-21T09:26:24.103 に答える
1

@バーンズ

イアンの答え (+1) は正しい[注を参照]。多対多のテーブルQUOTEMESSAGEを使用して結合QUOTEするMESSAGEのが最も正しいモデルですが、孤立MESSAGEしたレコードが残ります。

これは、トリガーを使用できるまれなケースの 1 つです。MESSAGEただし、単一のレコードが と の両方に関連付けられないように注意する必要がありQUOTEます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

Ian に注意してください。 のテーブル定義にタイプミスがあると思います。JobMessage列があるべき場所JobId, MessageId(?)。あなたの見積もりを編集しますが、そのレベルの評判を得るには数年かかるかもしれません!

于 2008-08-21T11:56:57.347 に答える
1

私が考えることができる他の唯一の方法は、Id と TypeId の両方を持つベース メッセージ テーブルを持つことです。次に、サブテーブル (QuoteMessage および JobMessage) は、MessageId と TypeId の両方でベース テーブルを参照しますが、適切な MessageTypeId のみを適用するためにそれらに CHECK CONSTRAINTS も設定します。

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

JobMesssage および QuoteMessage テーブルと比較して、これによって何が得られますか? 単一のテーブルからすべてのメッセージを読み取ることができるように、メッセージを第一級市民に昇格させます。代わりに、Message から関連する Quote または Job へのクエリ パスは、もう 1 つ離れています。それが良いトレードオフであるかどうかは、アプリのフローに依存します。

DRYに違反する2つの同一のテーブルについては、私はそれに夢中になりません。DB 設計では、DRY よりも正規化が重要です。モデリングしている 2 つのものが同じ属性 (列) を持っているが、実際には異なるもの (テーブル) である場合、同様のスキーマを持つ複数のテーブルを持つことは合理的です。さまざまなものを一緒にいじる逆よりもはるかに優れています。

于 2008-08-21T09:48:49.573 に答える
0

メッセージ テーブルに QuoteId フィールドと JobId フィールドの両方を持たないのはなぜですか? それとも、メッセージは見積もりまたは仕事の両方ではなく、どちらかに関するものである必要がありますか?

于 2008-08-21T19:44:31.217 に答える