允许空值与默认值

时间:2009-04-24 14:03:26

标签: asp.net database domain-driven-design

我正在开发一个替代许多现有纸质表单的ASP.NET项目。其中一个要求是用户可以将表单保存在任何状态,即他们可以创建一个新的空白表单并立即保存它没有数据或部分数据。我正在验证每次保存的数据类型,但在用户将表单标记为已完成之前,不会对必填字段进行验证。

我不确定在数据库和域模型中处理此要求的最佳方法是什么。在我看来,我有两个选择:

  1. 允许任何可能没有数据的字段的空值。这感觉就像“正确”的方法,但它要求几乎每个数据库字段都允许空值,我必须编写许多可空类型的代码。此外,在表单最终确定时,数据库中不会强制执行任何必填字段。
  2. 使用有意义的默认值填充业务对象。在某些情况下,我可以使用的许多(但不是全部)字段都有有意义的默认值。这种做法接近“魔术数字”,这让我感到不舒服。
  3. 哪种方法最好?还是有第三种方式?我不愿意走极端,比如拆分桌子。

    编辑补充:我想接受一个回应,我想稍微扩展一下。我对分割表不感兴趣的主要原因是,一旦提交了项目,表单上的数据将用于为另一个系统生成数据,该系统是记录系统。此时,原始表单数据不太可能被修改或用于报告。

10 个答案:

答案 0 :(得分:2)

我不明白为什么你不想拆分表。我不知道你在哪个领域,但我认为有两类人:

  • 已提交表单的人
  • 没有
  • 的人

作为一名商业主管,我不关心第二个问题。但我首先关心的是,他们需要正确地掌握所有数据。

它还提高了效率 - 您对聚合数据的大多数查询都将在第一个表上,而不是第二个表。第二个表仅用于索引搜索。

答案 1 :(得分:2)

如果拆分表(不止一个?)不是一个选项,我会考虑创建单个表来存储不完整表单对象的序列化,并且只在将表单提交到“真实”表时表格完全由用户提交。

答案 2 :(得分:1)

如果没有合理的默认值,并且您不想拆分数据,那么空值几乎肯定是您的最佳选择。重建数据库不是在完成时验证它们不是空的...好吧,如果你不想拆分表,那么你可以做的就是没有多少(没有使用CHECK约束,或者一个INSTEAD OF触发器来运行验证)。但是DB不是唯一负责数据验证的地方。您的应用程序逻辑也可以这样做。

答案 3 :(得分:1)

您可以在每列上使用带有“allow nulls”的临时表来存储包含部分数据或不包含数据的表单,并在用户将表单标记为已完成时将数据复制/移动到最终表。这样,您不依赖于默认值(用户可能忘记更改),您可以保存在任何状态,并且您仍然可以进行验证。

答案 4 :(得分:1)

这种情况迫切需要拆分表。我知道你说你不想这样做,并且在评论中甚至说“这个项目并不能保证这种努力”。但它确实是最好的解决方案。

使用除密钥可为空之外的所有内容设置初步表。当用户标记表单完成并通过验证时,将其移至最终表格。这不仅是正确的事情,而且在使用完成的表格时,它可能比“围绕可空值编码”更省力。

如果您需要查看所有表格,是否已完成,请进行联盟视图。

答案 5 :(得分:0)

我将采用第一个选项,但在数据库表中添加一列,以便在表单完成时标记。然后,对于使用表单数据的任何内容,它只需要检查表单是否已完成。

这是我建议的方法。

答案 6 :(得分:0)

NULL值无法通过索引进行搜索。

如果您需要发出类似“选择前10个表单且未填充某个字段”的查询,则此查询将使用可能无效的FULL TABLE SCAN

Oracle不区分NULL和空字符串,但其他数据库也可以。您可能希望将空字符串设置为未填充字段的DEFAULT,并在搜索中使用它。

如果您不需要搜索未填充的字段,只需将它们设为NULL

答案 7 :(得分:0)

检查约束+视图

如果您没有状态字段,请添加一个,以便您可以确定它已完成。

  • 在该状态字段上添加检查约束,以便在任何列为空时无法将其标记为已完成。

当您在“已完成”表单上编写查询时,如果您执行以下两个选项之一,则可以忽略在任何地方检查空值:

  • 只需在where子句
  • 中添加Status =“F”
  • 仅查看已完成的

使用“完成视图”时,您不必进行所有验证检查,也不必担心结果中出现未完成的检查

答案 8 :(得分:0)

NULL通常表示“不知道”(在数据库中),而空字符串实际上可以表示空字符串。

在您的情况下,我倾向于使用NULL作为“不知道”值。打印数据时,您只需假设任何NULL值表示空字符串。

答案 9 :(得分:0)

我遇到了类似的情况,虽然我还没有提出解决方案,但我一直在想要使用简单的XML序列化来存储临时文档数据。如果生成对对象中的数据建模的简单类(可能需要使用可空类型),则可以很容易地将数据从屏幕填充到这些对象中,将它们序列化为XML,然后将它们存储在临时的“暂存”中表。当您的用户完成工作并希望提交或最终确定文档时,您将对序列化数据执行所有必需的验证,最终将其放入具有适当数据结构和约束的“真实”表中。