2

在设计用于存储简单用户/角色信息的数据库表时,谁能告诉我为什么将角色信息直接存储在用户表中是一个坏主意(例如,在角色列中以逗号分隔)。

想法:

  1. 数据库不需要知道角色,那是 UI 的域
  2. 访问特定用户角色的速度越快越好
  3. 当然,如果将来某个时候我想访问特定角色的所有用户,则查询可能

慢一点,但谁在乎呢?

这有道理吗?我是不是摇摆不定?创建 Roles 和 UserRole 表会不会过大并增加不必要的 sql 和代码开销?

更新:

为了进一步说明我的观点......在代码中,我想知道用户“Steve”是否扮演“管理员”角色。

选项 1:查询 UserRole 表以获取用户“Steve”的角色列表。遍历该列表并查看 RoleName 是否与“Administrator”匹配。

选项 2:拆分用户角色属性中的 csv 并查看结果列表是否包含“管理员”

更新二:

我同意我的建议违反了各种“最佳实践”类型的思维,尤其是在数据库设计方面。但是,我没有看到“最佳实践”在这种情况下有何意义。我确实喜欢不时改变最佳实践……我喜欢以一种看起来很聪明的方式编码,这意味着有时我需要了解更多才能知道我什么时候不聪明:)

4

5 回答 5

2

因为它违反了第三范式。您想将所有实体分隔为不同的对象,这意味着您需要一个单独的表以及一个关系表。

违反数据

如果您将所有这些都保存在一个表中,那么您在用户表中放置了太多关于用户的不相关信息。用户的表应该包含仅与该用户相关的字段,例如他们的姓名、用户帐户等。但在这种情况下,您决定输入一些角色信息。这没有任何意义,因为您添加的属性不一定与用户有任何关系。

结果是您开始添加与用户无关的字段,最终获得大量不相关的信息。解决方案是有一个像这样的用户表:

User table
UserID
User
...

Role table
RoleID
Role
....

User Role Table (the relationship)
UserRoles
UserID
RoleID
...

更新/插入数据

如果您将角色信息存储在用户表中,您必须处理的下一个问题是如何执行有效的更新、插入。这使得这一切变得更加困难。编辑记录时,您必须确保从 CSV 编辑正确的值。

寻找合适的角色

这里是最困难的问题,如何找到给定用户的角色。您可能会在 C# 或 SQL Server 中提出这种出色的解析技术,它工作得很好……但它变得非常缓慢且难以阅读。您开始处理SubString(), Left(),Right()Len()一大堆其他函数,只是为了解析出用户的角色。

解决方案

您可能认为现在将所有内容放在一张表中更容易。可能需要更少的前期时间。但是您必须在开发应用程序时考虑到未来。如果您遵循 3nf 的规则并创建一个不错的关系结构,那么 UI 将会简单得多。不仅 UI 管理屏幕看起来不错,而且获取特定 UserID 的角色将非常简单,而不是解析或搜索......

于 2011-06-06T19:36:34.970 回答
1

我不认为这是一个伟大的计划。假设您手动更新某人的角色并且您键入的角色名称稍有错误?如果你有一个单独的表,数据库约束会警告你。假设您决定更改角色的名称?如果你有一张单独的桌子,你只需要在一个地方改变它。

数据库规范化是有充分理由的;这不仅仅是挑剔。您不会在多个地方重复代码库中的关键代码;数据库非规范化是等效的。

编辑添加:您指出应用程序最终将根据数据库返回的值做出决策;例如,如果用户具有称为“管理员”的角色,则授予某些选项。这是真的,它是另一个独立的地方,例如,角色名称的一致性可能会出错。我认为非规范化数据库不会降低这种可能性。

解决此问题的一种好方法(以及实现一般授权的一种好方法)是在代码中拥有一个位置,将角色转换为某些通用能力(例如,管理员可以读取和写入所有实体,客人可以读取某些实体并且不能写任何东西,等等)。然后,在您需要建立访问权限的许多地方,您检查能力,而不是检查角色。

也就是说,在一个视图中,如果你决定是否在一个项目的描述上显示“编辑”按钮,你不是通过做检查,而是通过做if role=='ADMIN' or role=='EDITOR'检查if user.can_edit(item)。在其他地方,您已经确定管理员和编辑者能够编辑项目。例如,参见 Rails 授权系统CanCan使用的方法。

使用这种方法,只有一个地方引用角色的名称(例如,在 CanCan 中有一个名为“能力”的类,它根据角色定义了谁可以做什么的所有规则。在其他任何地方,你参考用户具有哪些能力来确定他们可以做什么或看到什么。

于 2011-06-06T19:40:11.467 回答
0
  1. 您需要额外的逻辑来在代码端解析 CSV。
  2. 大多数 ORM 不支持 CSV。
  3. 如果您的角色名称很长(例如 UserWhoHaveAccessToXObjButNotYObjAndAtTheSameTimeCanDoZ),那么您将浪费空间为所有用户重复它。

此外,您的第一个假设并不适用于所有情况。如果我的数据库需要了解角色怎么办?

于 2011-06-06T19:41:51.053 回答
0

这取决于您是希望数据库管理系统管理数据还是希望应用程序管理数据。在大多数情况下,DBMS 做得更好,因为它就是为此而构建的。

于 2011-06-06T20:32:35.060 回答
-1

你说

那么为什么不只在应用程序中定义角色,并且只在应用程序中定义角色呢?

只有当你能够如实说:“我 100% 确信每个程序员和每个数据库管理员都将手动完美地保持数据完整性,无论什么应用程序触及这个数据库,无论它是用什么语言编写的,无论程序员有多么有经验或多么缺乏经验,无论数据库变得多么复杂,从现在到它生命的尽头。”

如果您在职业生涯中管理一个编程项目,那么您的部分工作就是将编码职责分配给最适合执行它们的人。在架构级别,有人还将程序职责(如数据完整性)分配给最适合执行它们的模块或子系统。只有将责任分配给 dbms才能保证数据完整性将其分配给系统的任何其他部分,无论是代码还是人类,都只是一种希望的表达,而希望并不能很好地扩展。

于 2011-06-06T22:54:05.787 回答