【问题标题】:EF CodeFirst handling database exceptions while saving changesEF CodeFirst 在保存更改的同时处理数据库异常
【发布时间】:2023-03-09 12:50:01
【问题描述】:

由于 EF 不支持唯一键约束,看来我们需要在 Save 方法期间捕获异常,并向用户显示错误消息。

这种方法的问题是:

  • 我们如何知道哪条记录引发了异常
  • 我们如何知道什么样的问题引发了异常(例如,我可以在同一记录上有两个唯一的约束,所以我需要告诉用户哪个被破坏了)

DBMS 是 SqlServer 2008。

如何解决这些问题?

【问题讨论】:

    标签: entity-framework entity-framework-4 ef-code-first


    【解决方案1】:

    如果您允许用户输入在数据库中必须唯一的值,您应该在保存更改之前验证此输入:

    if (context.Customers.Any(c => c.SomeUniqueProperty == userInput))
        // return to user with a message to change the input value
    else
        context.SaveChanges();
    

    这不仅适用于数据库中具有唯一约束的值,也适用于输入必须引用现有目标记录或主键值的外键值,如果主键不是在数据库中自动生成的。 EF 在后一种情况下对您没有帮助,因为上下文不知道整个数据库表的内容,而只知道当前附加到上下文的实体。确实,EF 将禁止附加具有相同主键的两个对象,但允许具有相同唯一键约束的两个对象。但是,当您将更改保存到数据库时,这并不能完全防止您违反主键约束。

    在不太可能的情况下,在Any 检查和SaveChanges 之间另一个用户输入了具有相同值的记录,我会认为发生的异常是无法处理的,只是告诉用户“发生了预期的错误, 请再试一次...”。如果用户再次尝试Any 检查再次发生,他将获得更有用的消息来更改上面代码中的输入值。

    针对此类唯一键约束或主键约束违规返回的异常是一般的DbUpdateException,而内部异常之一是SqlException,其中包含SQL Server 错误代码作为其属性之一。任何其他详细信息只能在异常消息“Violation of UNIQUE KEY constraint IX_SomeUniqueProperty_Index...”或类似消息中找到。如果您希望用户能够理解并对此信息做出相应的反应,您可以显示它。否则,您可以记录此消息以供管理员或开发人员检查可能存在的错误或其他问题。

    【讨论】:

    • 所以,由于我正在进行批量更新,这将需要在客户中查找更新/添加的记录,并遍历每条记录以检查是否存在具有相同值的现有记录。当有 10 多条记录被更改时,我不太确定它对性能有何影响。或者在这种情况下最好只捕获一个异常?消息必须本地化,所以看来我需要创建一个程序来搜索 IX_SomeUniqueProperty 的消息,因为消息也可以是法语,如果操作系统是法语(如果我没记错的话),我不能依赖关于“违反……”
    • @Goran:我明白了,但我仍然会进行查询以检查是否存在。如果您还需要更新,而不仅仅是插入,您是否还需要查询数据库中的实体?在不知道实体是否已经在数据库中的情况下,您无法决定更新和插入。
    • 更新和插入之间的决定由 EF 自己做出。我添加到客户集合中的任何实体都被视为新记录,已分配 PK 的记录将被更新。我需要介绍的是网络上的用户添加了一条记录的情况(客户端的数据在大多数情况下都不是最新的数据库数据,因为这需要不断地重新同步),所以最后一次之间可能有 15 分钟的间隔数据加载,并保存更改调用。出于这个原因,我不能只依赖缓存在客户端上的数据来检查是否唯一(或任何其他)约束。
    • 我不太确定我是否理解您对什么有疑问?基本上,您从数据库(DbContext 客户集)加载客户列表。在添加新项目方法中,您创建一个新客户,为其分配默认值,并将其添加到上下文的客户集。 EF 会将其标记为新项目,并在调用 SubmitChanges 时执行 INSERT INTO 语句。
    • @Goran:是的,我同意这一点。但这只是一个插入,而不是更新。如果新客户在唯一键属性中具有数据库中另一条记录已有的值,您将收到异常(“无法插入重复键...”)。如果要更新该现有记录,则必须查询它,然后加载它、更改属性并保存更改,或者将状态设置为已修改并保存更改。对我来说,这将是直接的方式。您似乎有尝试插入的想法,如果遇到异常,您知道必须重复更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-03
    • 2021-07-21
    • 1970-01-01
    • 2017-01-30
    • 2019-05-02
    • 2018-03-07
    • 2010-09-28
    相关资源
    最近更新 更多