代码之家  ›  专栏  ›  技术社区  ›  trendl

我应该检查代码中的db约束,还是应该捕获db引发的异常

  •  15
  • trendl  · 技术社区  · 16 年前

    我有一个将数据保存到名为jobs的表中的应用程序。jobs表有一个名为name的列,该列具有唯一约束。名称列不是主键。我想知道在保存/更新新条目之前是否应该自己检查重复条目,或者最好等待数据访问层抛出异常。我在用nhibernate来开发这个应用程序


    感谢大家的大力投入。

    我发现了另外一个原因,为什么我应该在代码中进行验证,而不仅仅是等待抛出异常(并被我的代码捕获)。似乎nhibernate只会抛出一个nhibernate.exceptions.genericadeoexception,在本例中,它对异常的原因没有太多的信息。或者我在这里遗漏了一个NHibernate的方面?

    8 回复  |  直到 12 年前
        1
  •  13
  •   ConcernedOfTunbridgeWells    16 年前

    答案是:两者皆有。

    如果数据库有约束,它可以保证数据的某些不变量,例如唯一性。这在以下几个方面有帮助:

    • 如果你身上有虫子 申请,违反 约束将标记 否则可能不会被注意到。

    • 数据库的其他用户可以 更多地假设 数据库管理系统执行的数据 不变量。

    • 数据库保护自己不受 不正确的更新违反了 约束条件。如果你发现你还有别的 填充 数据库在轨道上, 数据库强制的约束 意思是任何被 约束不会(或者至少不会 不太可能)破坏你的系统。

    应用程序和数据库在除了最琐碎的情况之外的任何情况下都处于m:m关系中。应用程序仍应具有适当的数据和业务规则验证,但您仍不应计划将应用程序作为数据的唯一客户。在数据仓库领域工作几年,你会看到有这种想法的人设计的应用程序的效果。

        2
  •  4
  •   dkretz    16 年前

    如果您的设计是好的(数据库和bl),那么数据库不应该有bl中没有处理的任何约束,也就是说,您不应该用不一致的数据呈现数据库。但没有什么是完美的。

    我发现,将数据库限制为数据一致性约束可以让我在过程代码中处理所有bl验证,而我遇到数据库异常的唯一情况是可以(而且应该)修复的设计和编码错误。

    在您的例子中,检查名称的唯一性是数据内容验证,在代码中正确处理。这可能会捕捉到离委托点最近的错误,在委托点,您希望有更友好的ui资源来调用,而不会在抽象之间引入不需要的耦合。

        3
  •  3
  •   JosephStyons    16 年前

    我将把这项工作完全交给数据库处理;您的代码应该专注于捕获和正确处理异常。

    原因:

    1. 性能 -数据库将是 高度优化以执行 快速有效的约束 方式。你没时间了 同时优化你的代码。
    2. 可维护性 -如果约束条件 未来的改变,你不会有 修改代码,或者 只需要添加一个新的catch{}。 如果删除了约束,则 不必在 所有。
        4
  •  2
  •   Kon    16 年前

    如果要自己检查约束,请在数据访问层中进行检查。该层之上的任何内容都不应了解数据库或其约束。

    在大多数情况下,我会说让dal来捕获源于db的异常。但在你的具体案例中,我认为我们讨论的是基本输入验证。在提交整个表单之前,我会选择对数据库进行名称可用性检查调用。

        5
  •  1
  •   Simon Lehmann    16 年前

    您一定要检查数据访问层引发的任何异常。检查是否存在具有相同值的记录的问题是,在插入新记录以防止出现争用情况之前,需要锁定表以进行修改。

    一般来说,检查异常/错误是明智的,即使您以前已经检查过所有内容。几乎总是有一些可能出错的东西,或者您在代码中没有考虑但由数据库强制执行的东西。

    编辑: 如果我正确理解这个问题,那就不是数据库是否应该强制执行约束,而是如何在应用程序代码中处理它。你当然应该 总是 设置数据库中的所有约束以防止错误数据进入数据库。

        6
  •  1
  •   Dani Cricco    15 年前

    你需要回答的问题是:

    “我需要向用户展示好消息吗”。示例:已经有一个名为testjob1的作业。 如果答案是 ,只需捕获错误并显示一条公共消息 如果答案是 是的 ,继续阅读

    如果你 捕捉插入后的错误 没有足够的信息来显示正确的消息(至少以不可知的数据库方式)

    另一方面,可能有 竟态条件 您可以让同时事务尝试插入相同的数据,因此您需要 数据库约束

    一种行之有效的方法是:

    • 检查之前,提出一个不错的 消息
    • 捕捉异常并 显示常见错误消息 (假设这不会发生 经常)
        7
  •  0
  •   Rad    16 年前

    就我个人而言,我会抓住例外。它简单得多,需要的代码也少得多。

        8
  •  0
  •   Matt Sharpe    16 年前

    GenericaDoException的内部异常将告诉您数据库操作失败的原因。您可以捕获OracleException/mssqlException/[insertCustomExceptionHere]并处理该消息中的错误。如果您想将此消息传递回前端(假设输入重复数据的是用户),您可能需要首先将其包装为自定义异常,这样就不会将前端连接到数据库。您不希望到处传递特定于rdbms的异常。

    我不同意在执行插入之前检查数据库的唯一性,两次往返数据库的效率不高,而且如果用户流量很大,肯定无法扩展。