3

这是我的数据库的简化:

表:属性
字段:ID、地址

表:报价
字段:ID、PropertyID、BespokeQuoteFields...

表:工作
字段:ID、PropertyID、BespokeJobFields...

然后我们有其他表分别与QuoteJob表相关。

我现在需要添加一个Message表,用户可以在其中记录客户留下的关于 Jobs 和 Quotes 的电话消息。

我可以创建两个相同的表(QuoteMessageJobMessage),但这违反了 DRY 原则并且看起来很混乱。

我可以创建一个消息表:

表:消息
字段:ID、RelationID、RelationType、OtherFields...

但这阻止了我使用约束来强制执行我的参照完整性。我还可以预见它会在以后使用 Linq to SQL 与开发方面产生问题。

这个问题是否有一个优雅的解决方案,或者我最终将不得不一起破解一些东西?

伯恩斯

4

4 回答 4

4

创建一个 Message 表,其中包含唯一的 MessageId 和您需要为消息存储的各种属性。

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

创建两个链接表 - QuoteMessage 和 JobMessage。这些将仅包含两个字段,即报价/作业和消息的外键。

Table: QuoteMessage
Fields: QuoteId, MessageId

Table: JobMessage
Fields: JobId, MessageId

通过这种方式,您只在一个地方定义了 Message 的数据属性(使其易于扩展和查询所有消息),但您还具有将 Quotes 和 Jobs 链接到任意数量的消息的引用完整性。实际上,报价和工作都可以链接到一条消息(我不确定这是否适合您的业务模型,但至少数据模型为您提供了选择)。

于 2008-08-21T09:26:24.103 回答
1

关于我能想到的唯一另一种方法是拥有一个基本的消息表,其中包含一个 Id 和一个 TypeId。然后,您的子表(QuoteMessage 和 JobMessage)在 MessageId 和 TypeId 上引用基表 - 但它们上也有 CHECK CONSTRAINTS 以仅强制执行适当的 MessageTypeId。

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 表相比,这能为您带来什么?它将消息提升为一等公民,以便您可以从单个表中读取所有消息。作为交换,您从消息到相关报价或工作的查询路径是另外 1 个连接。这取决于您的应用程序流程,这是否是一个很好的权衡。

至于违反 DRY 的 2 个相同的表 - 我不会挂断电话的。在 DB 设计中,它与 DRY 无关,而更多地与规范化有关。如果您正在建模的 2 个事物具有相同的属性(列),但实际上是不同的事物(表) - 那么拥有多个具有相似架构的表是合理的。比把不同的东西混在一起要好得多。

于 2008-08-21T09:48:49.573 回答
1

@烧伤

伊恩的回答 (+1) 是正确的[见注释]。使用多对多表QUOTEMESSAGE连接QUOTEMESSAGE最正确的模型,但会留下孤立MESSAGE记录。

这是可以使用触发器的极少数情况之一。但是,需要注意确保单个MESSAGE记录不能同时与 aQUOTE和 a关联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 回答
0

为什么不在消息表中同时包含 QuoteId 和 JobId 字段?或者信息是否必须与报价或工作有关,而不是两者兼而有之?

于 2008-08-21T19:44:31.217 回答