【问题标题】:Database exception handling best practices [closed]数据库异常处理最佳实践 [关闭]
【发布时间】:2010-09-07 13:13:20
【问题描述】:
您如何处理应用程序中的数据库异常?
您是在将数据传递给数据库之前尝试验证数据还是仅仅依赖数据库架构验证逻辑?
您是否尝试从某种数据库错误(例如超时)中恢复?
这里有一些方法:
- 在将数据传递给 DB 之前验证数据
- 将验证留给 DB 并正确处理 DB 异常
- 双向验证
- 验证业务逻辑中一些明显的约束,并将复杂的验证留给 DB
您使用什么方法?为什么?
更新:
我很高兴看到越来越多的讨论。
让我们尝试总结社区的答案。
建议:
你还有什么要说的吗?这将转换为验证特定问题。我们缺少核心,即“与数据库相关的错误最佳实践”,哪些要处理,哪些要冒泡?
【问题讨论】:
标签:
database
exception
architecture
【解决方案1】:
在客户端和数据库端都需要验证一个杀手锏,那就是安全。尤其是当您开始使用 AJAX 材料、可破解 URL 和其他使您的网站(在这种情况下)对用户和黑客更友好的东西时。
在客户端上进行验证以提供流畅的体验,以便及早告诉用户更正他们的输入。还要在数据库中验证(或在业务逻辑中,如果这被认为是通往数据库的完全安全网关),以确保您的数据库安全。
【解决方案2】:
对象关系映射 (ORM) 工具,例如 NHibernate(或者更好的是 ActiveRecord),可以帮助您避免大量验证,因为它允许将数据模型直接构建到您的代码中C# 类。由于框架中内置了出色的缓存和验证模型,您也可以避免访问数据库。
【解决方案3】:
@aku:DRY 很好,但并不总是可行。验证就是其中之一,因为您将拥有三个完全不同且不相关的地方,验证不仅可能而且绝对需要:在 UI 内、业务逻辑内和数据库内。
想想一个网络应用程序。您希望减少对服务器的访问,因此您包括客户端数据输入的 javascript 验证。但是您不能相信用户输入的内容,因此您必须在接触数据库之前在业务逻辑中执行验证。并且数据库必须有自己的验证,以防止数据损坏。
没有一种简洁的方法可以将这三种不同类型的验证统一在一个组件中。
正在尝试统一跨领域职责,例如 P&P 小组的 Policy Injection Application Block 与他们的 Validation Application Block 等策略注入器中的验证,但这些仍然是基于代码的。如果您有代码中没有的验证,您仍然需要单独维护并行逻辑...
【解决方案4】:
我正在编写的那种应用程序(我已经换了工作)是内部的胖客户端应用程序。
我会尝试将业务逻辑保留在客户端中,并在数据库上进行更多的机械验证(即仅与程序运行能力相关的验证,而不是更高级别的验证)。
简而言之,尽可能验证,并尝试将相关类型的验证放在一起。
【讨论】:
-
@hamishmcn。好点,在业务逻辑层进行验证的一个原因是创建用户友好的 UI。但是在多个地方进行这些验证会破坏 DRY 原则。您如何设法使数据库和客户端验证保持同步?
【解决方案5】:
您希望减少不必要的数据库访问,因此在应用程序中执行验证是一种很好的做法。此外,它还允许您在最容易恢复的地方处理数据错误:在输入数据的 UI 附近(无论是在控制器中还是在更简单的应用程序的 UI 层中)。
但是,您无法以编程方式检查某些数据错误。例如,如果不往返数据库,您将无法验证相关数据是否存在的数据。此类数据错误应由数据库通过使用关系、触发器等进行验证。
处理数据库调用返回的错误是一个有趣的问题。您可以在数据层、业务逻辑层或 UI 层处理它们。在这种情况下,最好的做法是让这些错误冒泡到最后负责的时刻,然后再处理它们。
例如,如果您有一个 ASP.NET MVC Web 应用程序,您有三层(从下到上):数据库、控制器和 UI(模型、控制器和视图)。你的数据层抛出的任何错误都应该被允许冒泡到你的控制器中。在这个级别,您的应用程序“知道”用户正在尝试做什么,并且可以正确地通知用户有关错误,建议不同的方法来处理它。尝试从数据层中的这些错误中恢复会使了解控制器中发生的事情变得更加困难。当然,将业务逻辑放在 UI 中并不是最佳做法。
TL;DR:到处验证,在最后负责的时刻处理验证错误。
【解决方案6】:
我尝试验证双方。我始终遵循的一条规则是永远不要相信用户的输入。在此得出结论后,我通常会在表单/网页上进行一些前端验证,甚至不允许提交格式不正确的数据。这是一个生硬的工具 - 这意味着您可以检查/解析该值以确保日期字段包含日期。从那里开始,我通常让我的业务逻辑检查数据输入在上下文中是否与它的提交方式有关。例如,提交的日期是否在预期范围内?提交的币值是否在预期范围内?最后,在服务器端,外键约束和索引可以捕获任何漏掉的错误,这将作为最后的手段冒泡一个 DB 异常,这可以由应用程序代码处理。我使用这种方法是因为它在调用 DB 调用之前尽可能多地过滤掉错误。
【解决方案7】:
一般来说,我会在输入数据后尽快对其进行验证。这样我就可以在用户点击“提交”或同等内容之前向他们提供有用的信息。
到进行 db 调用时,我希望我传递的数据应该相当好。
我尝试将 db 调用保留在共享辅助方法的一个文件(或一组文件)中,使程序员(我或其他添加调用的人)尽可能容易地写入有关异常的日志详细信息,以及哪些参数被传入等