向用户公开代理键
Posted
技术标签:
【中文标题】向用户公开代理键【英文标题】:Exposing Surrogate Key to Users 【发布时间】:2011-11-28 15:32:19 【问题描述】:我正在设计一个新应用程序,并且有一个表格,其中包含用户希望用数字唯一标识的项目。该表将有一个代理键,可用于此目的,但是我不确定是否应该将它公开给用户。他们只会将此 id 用作只读和查找,应用程序将在幕后处理密钥的创建。
这个想法是为了避免潜在的问题。如果密钥是由 dbms 自动生成的身份字段,则您无法控制密钥。我在我的应用程序中使用 NHibernate,因此我可以通过使用 HiLo 来控制密钥,如我打算使用的 here 所述。万一这很重要,DBMS 就是 Oracle。
暴露密钥后我可能会遇到哪些潜在问题?
-
让我们假设用户通过制作一些使用此键的 excel 电子表格来建立对它的依赖。密钥会改变吗?
如果某些记录在数据库损坏或事故中丢失,并且我想避免与旧键发生冲突,我不能在 NHibernate 中调整我的起点以跳过以前生成的数字吗?
如果用户想改用其他方法来识别他们的记录,该怎么办。假设他们想从一些有意义的字符代码开始。那么我可以不向他们显示一个计算的(未存储的)标识符,或者随时根据我的代理主键创建一个新的备用键列吗?
如果有人可以展示一个清晰的示例,说明将托管代理主键暴露给用户可能会成为一个问题,我将创建一个备用键来展示给用户,否则我将暴露代理主键。
谢谢!
【问题讨论】:
【参考方案1】:id 通常并且通常应该是实现问题,用户不应该关心它们。我建议您重新考虑是否真的需要向用户显示标识符。不知道您的具体情况,也许是这样,但我对此表示怀疑。用户不应该关心更新记录 12345 或者他们是客户 54321。用户应该只知道我正在更新我的地址或购买特定物品。
如果向用户公开标识符实际上只是让它出现在查询字符串中,那么使用代理主键是完全合适的。
如果确实是用户需要查看id的业务需求:
密钥不必更改,也不应该更改。 catcall 获取并将此信息合并到另一个数据库的示例是一种边缘情况,即使在获取中也可能不会发生,并且除了更改 id 之外还有其他方法,例如使用单独的表或创建复合键。我不会担心的。
是的,无论是身份还是 hilo,您都可以更改身份种子或更新 hibernate_unique_key 表以更新新 ID 的范围。我建议在使用 nhibernate 时,您永远不要使用身份,而总是偏爱 hilo(或 guid)。身份生成器需要访问数据库来获取 id,这与 nhibernate 喜欢在会话中批量处理操作并在刷新时访问数据库的方式形成对比。有些事情在 nhibernate 中不能很好地工作,如果你使用身份,你会看到一些微妙和意想不到的错误,因为在这种情况下,nhibernate 做的一些事情与你所期望的不同(而且有些事情不起作用)。
是的,这些当然是选项。
我不认为暴露 id 是个问题,只是在几乎所有情况下它可能并不是用户真正想要的。不过,没有技术上的理由不这样做。
【讨论】:
“重新考虑是否真的需要向用户显示标识符” 在大多数情况下,向用户显示 an 标识符肯定是一项要求。我认为这里的问题是 what 使用的关键。 @dportas - 如果您正在谈论显示一些自然键,那么您可能经常将其显示为要求 - 不是因为它是标识符,而是因为它是有趣的信息。如果您正在谈论向用户显示一个实际上是一些无意义的数字(或 guid)的代理键,我仍然认为在几乎所有情况下他们都不(好吧,不应该)关心它。我只是断言,如果业务用户要求一个毫无意义的数字,那可能是因为我们已经对他们进行了培训,ID 是事物的实现方式,而不是因为这就是他们真正想要的。 @Dave - 我支持你,但你对独特的物品识别有何建议?用户现在要求一个“毫无意义的数字”,因为他们没有看到更好的东西来满足他们的需求。 这取决于您的域。这取决于用户真正想要什么。 @dportas 有一个观点,即呈现选项并允许选择的应用程序具有一些与这些事物相关的识别信息。也许它是书名或产品名称或类似的东西,这是用户在从域中识别实体时真正考虑的东西。如果用户希望能够识别某物,则很少使用代理键。用户可以学习到处理他们需要处理数字的系统,但这不是他们看待业务的方式。 我认为一般来说,用户有兴趣以他们对项目的看法来识别项目(这可能不是普遍唯一的(如名称),但足以让他们在上下文中做出决定他们想要什么)。向他们展示一个人为的数字很少是他们真正想要的。【参考方案2】:前三个问题很简单
-
不容易。这是代理键的主要好处。当候选键是主键时,可以更改的候选键可能会导致问题。
是的,但你不应该因为 #1
是的,你应该这样做。
这个比较难。
如果有人可以展示一个清晰的例子来说明如何公开托管 用户的代理主键可能会成为一个问题 将创建一个备用密钥以呈现给用户,否则我将 公开代理主键。
但是有两个常见的问题。
用户习惯于看到没有孔的数字增量。但迟早他们会得到一个或多个,他们会要求填补这些漏洞。他们不是很多好的理由,你需要推回这一点。
如果您的系统允许通过 ID 查找或更糟糕的通过 ID 输入数据,您可能会遇到问题。这是因为带有数字的拼写错误非常容易。信用卡号码使用 Hamming 函数,因此很难输入有效号码的信用卡号码。
因此,如果您确保您的用户不利用代理键的顺序特性并且您不将其用于用户数据输入,那么您应该没问题,否则您可能需要考虑使用密钥生成您可以在其中检测错别字。
【讨论】:
禁止通过 ID 引用似乎违背了代理 ID 的既定目的。 好吧,我并不是要“禁止”它们,但标准解决方案确实存在可预测的问题。如果利益相关者想要采取不同的方式,那么他们将拥有更多权力。【参考方案3】:代理键可以改变吗?是的。假设您的公司被另一家公司收购,他们决定合并数据库。如果某人的身份证号码必须更改,那将是您的,而不是他们的。我参与了两次这样的系统整合,它不漂亮。
虽然我没有做过,但相信你可以在NHibernate中改变起点。 (在大多数 ORM 中,您至少可以创建自己的类,扩展 ORM 的类。然后编写您想要的行为。)
你能根据你的身份证号码向用户显示一个计算出来的密钥吗?一般情况下不会。当用户想出按键的想法时,它们通常不是很好,并且几乎总是需要一些手动调整。因此,您几乎可以肯定必须存储它。没有错。 (除了让用户设计具有编码含义的键。)
用户必须能够识别事物。 SQL 数据库使用键来识别事物。 要识别 SQL 数据库中的事物,用户至少需要查看一个 自然键。如果 . . .向用户公开托管代理主键可能成为 以后的问题,我将创建一个备用键来呈现给 用户,否则我将暴露代理主键。
(有例外,但不多。)
因此,如果您使用隐藏的代理键,则至少需要一个自然键才能呈现给用户。为什么是自然键?没有一个,您可能最终会得到这样构建的表格。
id title
--
1 An Introduction to Database Systems
2 An Introduction to Database Systems
3 An Introduction to Database Systems
4 An Introduction to Database Systems
8 An Introduction to Database Systems
15 An Introduction to Database Systems
37 An Introduction to Database Systems
但是通过隐藏代理,用户会看到这一点。
title
--
An Introduction to Database Systems
An Introduction to Database Systems
An Introduction to Database Systems
An Introduction to Database Systems
An Introduction to Database Systems
An Introduction to Database Systems
An Introduction to Database Systems
如果需要更新与这些标题之一相关的行,用户如何知道要选择哪个标题?
【讨论】:
在您描述的数据库合并场景中 - 听起来可以由我原始问题中的第 3 项处理,或者正如 Dave 在下面描述的 ***.com/a/8310521/265877【参考方案4】:如果希望用户准确地更新单个元组,那么他们将需要一个密钥来识别他们感兴趣的信息。这通常是所谓的业务密钥。代理键是没有业务意义的,通常这意味着它不会暴露给用户(否则它会在业务领域内获得意义)。
确保用户至少看到每个表的一个键当然是明智的。虽然不是“代理”键。如果一个键用于识别信息作为业务流程的一部分,那么它就不是真正的代理键,这样称呼它也没有多大意义。
所有键都可以并且确实有理由更改,包括代理。
【讨论】:
因此,如果我向用户显示代理键,那么我应该将其称为业务键。功能上没有什么不同,但现在可以这样做吗? 在功能上会产生很大的不同。该密钥在业务流程中的什么位置?您说用户需要一个“ID 来进行快速查找”,但在这样的交互中,“ID”从何而来?他们以前从未见过的任意数字对此毫无用处。确定或设计业务标识符的方法是分析和理解业务需求。看来您有一些业务分析要做。还要问自己为什么首先创建代理。如果您想不使用它,那么这也可能是一个重要的考虑因素。 用户正在创建没有标识符的新项目。他们想要一个简单的 id 来查找项目。我/他们应该如何以不同的方式分析?用户和我已经确定我们需要代理键提供的内容。现在,我可以创建另一个类似于代理键的列,但是在这个阶段复制一个 ID 列有什么意义呢?使用代理键进行用户查找的陷阱的一个明显例子是什么?这是我的问题。 “用户查找”并没有解释他们实际在做什么。也许您的意思是:“密钥将记录在其他地方,用于业务流程的某些部分,因此用户将需要根据该密钥在表中查找数据”。那不是代理键。到目前为止没有问题。所以问题是你需要这个表的代理键吗?可能不是。根据定义,代理几乎是可选的和冗余的。不要在没有充分理由的情况下使用代理人。 明白了。我所说的查找是指一个用户告诉另一个用户在他们的计算机上查找记录 id 123。他们不需要在其他地方录制,尽管没有什么可以阻止他们这样做。底线,如果我不向用户公开它 - 它是一个代理键。如果我确实将它公开给用户 - 它是一个业务密钥,我真的不需要另一个代理密钥。谢谢。以上是关于向用户公开代理键的主要内容,如果未能解决你的问题,请参考以下文章