Sql server 实体框架。如何优雅地报告SQL约束错误

Sql server 实体框架。如何优雅地报告SQL约束错误,sql-server,entity-framework,validation,extjs,extjs4,Sql Server,Entity Framework,Validation,Extjs,Extjs4,我有一个web应用程序:ExtJs前端-EntityFramework+SQL Server作为后端。让我们来看一个错误场景: 我对用户名有数据库约束(名称必须唯一) 我没有任何客户端验证(我应该吗?有没有办法使这种验证通用?) 如果我尝试插入同名用户,服务器将返回500错误 如果我在IIS开启的同一台机器上运行它,我会收到完整的错误消息(基本上是SQL异常描述和密钥冲突等),如果我在其他机器上运行它,我只会收到500个错误,没有错误消息 处理这个问题的最佳方法是什么?我需要以一些人类可读的

我有一个web应用程序:ExtJs前端-EntityFramework+SQL Server作为后端。让我们来看一个错误场景:

  • 我对用户名有数据库约束(名称必须唯一)
  • 我没有任何客户端验证(我应该吗?有没有办法使这种验证通用?)
  • 如果我尝试插入同名用户,服务器将返回500错误
  • 如果我在IIS开启的同一台机器上运行它,我会收到完整的错误消息(基本上是SQL异常描述和密钥冲突等),如果我在其他机器上运行它,我只会收到500个错误,没有错误消息

处理这个问题的最佳方法是什么?我需要以一些人类可读的格式告诉用户错误。我真的不想在IIS上打开错误消息,因为这不是一个好的做法

首先,我建议您在提交到客户机上的服务器之前进行验证,向用户提供即时反馈是一种很好的体验

第二,对于实际插入的选项,您可以考虑几个选项:

  • 使用执行检查和插入的存储过程,并返回新记录作为成功插入的确认,这很容易处理事务并处理存储过程中的所有问题,但是现在您拥有了编译代码之外的功能
  • 在insert过程中,封装一个调用以验证事务中的第一个,并适当地处理它,为您提供编译代码和较低的外部依赖(如存储过程)复杂性,但是您对该层的事务锁类型有一些限制,但这是可行的
  • 尝试插入并捕获异常,并适当地处理它,这是我最不喜欢的

  • 我没有看到您提到更新
    用户名
    ,如果您允许此功能,您也必须在更新之前进行验证,因为在执行insert时存在相同的问题

    我认为这里没有错误,但是违反了业务规则

    我喜欢区分这两种情况,第一种是一些意外情况(如数据库连接丢失),第二种是可能发生的情况

    对于错误,我认为恰当的做法是以一般方式通知用户(比如,“发生了意外错误”),因为这是用户无法纠正的,也不需要详细信息

    另一方面,业务规则是用户可能理解并可以采取措施纠正的东西(这里是用户名约束)。所以应该通知用户

    在我参与的项目中,我们有一种异常类型,
    BusinessException
    。我们抛出一条消息,指出问题所在,并以人类可读的格式呈现。我们不会明确地尝试捕获这些异常,而是使用处理程序来管理它们。如果您使用的是MVC,那么有一个扩展钩子,您可以在其中执行此操作

    对于其他类型的异常,最好将stacktrace记录在某个位置(即EventViewer),但不向用户提供详细信息

    在这种情况下,我将执行以下操作:

    • 使用按钮检查名称以允许用户预先验证名称
    • 验证名称的位置取决于您希望将应用程序的业务逻辑放在何处。在DB上,使用存储过程是一种方法,但如果使用EF,这意味着您希望从数据访问中抽象出来。相反,您可以使用
      LINQ
      (类似于
      Context.Users.SingleOrDefault(x=>x.Name==Name))自己编写此验证
      然后检查它是否返回null或某个用户。您可能认为此验证不是必需的,因为您已经有了DB约束,但这样做,逻辑仍保留在应用程序的代码中
    • 从EF捕获异常可能很麻烦,因为您需要检查SQL错误代码以确定它是违反约束还是其他错误。即使您确定了这一点,您也需要将消息转换为用户友好的消息
    我希望这对你的决定有帮助

    我没有任何客户端验证(我应该吗?有吗 使这种验证通用化的方法?)

    我会一直这样做。您可以使用jquery ajax调用服务器页面并检查那里的数据。这让用户在单击submit按钮之前就知道用户名不可用。这提供了更好的用户体验。这种方法避免了另一次服务器往返(包含所有表单数据的正常表单过帐,然后收到错误)

    如果我尝试插入同名用户,服务器将返回500错误


    始终捕获代码中的异常并将其记录下来。向用户显示有关错误的友好消息。永远不要向最终用户显示异常的堆栈跟踪。如果使用ASP.NET,请使用自定义错误页功能。

    如果使用DbContext,则可以通过自定义内置验证来验证其唯一性。请看这篇博客:。最后有一个示例演示了如何执行此操作。

    我同意客户端验证。我真的不想有数百个存储过程,我希望在EntityFramework中找到一种通用方法来返回可接受的错误。你知道类似的事情吗?我的意思是我不知道nt有权访问CommitChanges功能(我用它来做这件事)-EF会自动将所有内容传输到InsertXXXX/Updatexx。感谢您的完整回答。我会像您所说的那样研究LINQ验证。我完全同意您的“业务与内部”错误点