以下是我目前的评论系统设计:
我正在为一个有很多领域,博客,教程,手册等的网站开发它。应该为每个(tblBlogComments
,tblTutorialComments
)等开发一个单独的评论表,我正试图采用一种适合所有方法的结构。
这样,我可以将评论系统转换为Web控件,只需将其放在我想要评论的任何页面上。这意味着我只有一套规则,一组代码文件需要维护。
唯一的问题是,提出了一个“好的”方法来确定属于哪个部分(博客/教程/手册)。
例如,一种解决方案是:
tblComment
-------------
Section (int)
SectionIdentifier (int)
“Section
”映射到网站每个部分的唯一位置,EG:
Blog = 1
Articles = 2
Tutorials = 3
...
SectionIdentifier
是该页面的某种唯一ID,例如:
ViewBlog.aspx?ID=5
这将是第1部分,标识符5.现在,Section = 1
,SectionIdentifier = 5
的评论意味着它是对博客条目号5的评论。
这很有效,但是以可维护性和可靠结构为代价,因为SectionIdentifier
是匿名的,不能建立任何关系。
这个设计是否正常,或者是否有更好的解决方案(IE某种父表用于评论?)
答案 0 :(得分:3)
在Codd最初为关系模型设计的内容中,外键可以引用不同表中的多个主键,如果任何一个表包含该值,则引用完整性有效。
不幸的是,SQL是对原始愿景的一种苍白反映,因为它没有像你所指出的那样提供这种能力。
一个标准的解决方法是创建一个新的关系,其中包含所有其他关键字。但在这种情况下,这不是一个非常好的解决方案,因为如果一次发生大量插入,它会产生争用点。
我处理这个的方法是创建一个值 - 让我们称之为Comment-Anchor - 你可以把它放到每个有评论的表中。此值(与设计良好的数据库中的所有其他键不同)应为GUID。然后每个注释都可以有一个Comment-Anchor,指示它引用的值。
通过将其设为GUID,您可以随时在博客或教程中插入唯一值,而无需争用。您不必在任何地方维护Comment-Anchors的主列表,也不必与任何其他部分争用或阻止。
这对于查找单个博客条目的所有评论的正常用例非常有用。换句话说,从评论到被评论的东西,你可以在评论表中放置一个标志来识别哪个表被引用,但我不会这样做。我会搜索所有表格,也许是查看或其他内容。反向查询是非常罕见的,我没有看到维护它的基础设施有多大意义,而标志将是冗余数据,这是RDBMS的祸根。
该系统的另一个好处是它易于扩展。如果您创建新类型的数据,或决定向现有数据类型添加注释,则只需将Comment-Anchor列添加到表中。不必在数据库方面进行额外的工作。甚至处理注释的中间件部分也不需要以任何方式进行修改,因为它不知道哪些内容需要注释。
答案 1 :(得分:2)
对于表格设计,我会尽可能地模拟它在这种情况下的类结构。从你所说的,这就是它的样子(粗略地):
Section <- Post <- Comment
所以,你有:
每个帖子都会引用它的部分,每个评论都会引用它的帖子。数据库可以将引用作为漂亮,干净的外键,并且类可以在应用程序需要时在关系的一侧或两侧具有列表。
对我来说,这看起来像一个漂亮,简单,灵活的结构,不会使事情变得复杂,仍然允许你挂掉额外的位,比如编辑和投票。
答案 2 :(得分:1)
我将避免创建一个id列,该列根据同一个表中的另一列定义不同的关系。例如,在您的示例中,SectionIdentifier
可以表示任意数量的外键引用,具体取决于Section
的值。这使我在一般原则上屈服了。它还保留了现代RDBMS平台的几个优点,因为它不受支持。
这些不同部分的总体架构是如何构建的?我已经使用了一些CMS,这些CMS需要您的每个部分共享一个公共基础实体,称之为“模块”或“插件”。然后,给定模块的每个实例都有自己的id,用于映射到该特定实例所需的任何内容。
如果这是一个可行的架构方向,您也可以使用ModuleInstanceID
作为注释的外键。您只需要决定如何将给定类型的模块/插件注册为有效的评论目标。
无论如何,你能否透露一下如何将你的部分放在引擎盖下?
答案 3 :(得分:0)
好像。您的评论系统包含许多类型的评论(tblBlogComments,tblTutorialComments .....等)。我想建议你采用策略设计模式。
让我们说吧。你有一个IComment接口。并且所有类型的注释类都实现了IComment接口。
interface IComment
{
int ID {get; set; }
int Section {get; set; }
....
}
class BlogComment : IComment
{
....
}
class TutorialComment : IComment
{
....
}
一个只知道如何处理IComment的WebControl
class WebControl
{
IComment _comment = null;
public WebControl(IComment comment)
{
_comment = comment;
}
}
当然,您需要一个CommentCreater来加载来自数据库的注释数据并构建注释对象。
public static void main()
{
var creater = new CommentCreater();
IComment comment1 = creater.CreateBlogComment()
WebControl webcontrol = new WebControl(comment1);
......
IComment comment2 = creater.CreateTutorialComment()
webcontrol = new WebControl(comment2);
........
}
这样,您的网络控件就可以以同样的方式处理所有类型的评论。无论究竟是什么样的评论。你也可以保持CommentCreater正确构建每种评论类。
答案 4 :(得分:0)
查看this question的已接受答案。阅读所有评论。