何时使用 Microsoft.Data.SqlClient.SqlException 与 System.Data.SqlClient.SqlException?

Ror*_*ory 20 c# sql-server

据我了解,Microsoft 在 2019 年左右创建了 Microsoft.Data.SqlClient作为 System.Data.SqlClient 的替代品。System.Data.SqlClient 将持续受到支持,但新的开发和功能将全部位于 Microsoft.Data.SqlClient 中。这两个库都有一个名为“SqlException”的类。

假设我到处使用 Microsoft.Data.SqlClient 那么大概相关的异常将是 Microsoft.Data.SqlClient.SqlException 类型,但是我使用了一堆第 3 方库,我如何确定它们是否会引发Microsoft .Data.SqlClient.SqlException还是System.Data.SqlClient.SqlException?这是否意味着在某些情况下,我有 Microsoft.Data.SqlClient.SqlException 的捕获处理程序,我还应该检查 System.Data.SqlClient.SqlException?或者是否发生了一些聪明的事情,这意味着我只需要考虑 Microsoft.Data.SqlClient.SqlException?

例如,我有一些旧代码,有点像下面所示,是在我们开始使用 Microsoft.Data.SqlClient 之前编写的。我担心如果我只是将其更改为使用 Microsoft.Data.SqlClient 那么将会出现一些 System.Data.SqlClient.SqlException 异常,并且我的代码将不再注意到它们。

    private static bool HandleSqlExceptionInSomeWay(Exception ex)
    {
        var se = ex as System.Data.SqlClient.SqlException;

        if (se != null)
        {
            // ... do something with the SqlException
            return true;
        }

        return false;
    }
Run Code Online (Sandbox Code Playgroud)

那么我应该将其更改为类似的内容,即分别检查不同类型吗?

    private static bool HandleSqlExceptionInSomeWay(Exception ex)
    {
        // handle old SqlExceptions (e.g. from any old 
        // libraries not using MS package yet)
        var se1 = ex as System.Data.SqlClient.SqlException;

        if (se1 != null)
        {
            // ... do something with the SqlException ...

            return true;
        }

        // handle shiny new SqlExceptions 
        var se2 = ex as Microsoft.Data.SqlClient.SqlException;

        if (se2 != null)
        {
            // ... do something with the SqlException ... 

            return true;
        }

        return false;
    }
Run Code Online (Sandbox Code Playgroud)

Pan*_*vos 12

这两个类不同,但它们继承自相同的基类DbException。这是所有数据库异常的公共类,并且不会具有两个派生类中的所有属性

您应该检查您使用的库/NuGet 包,并确保您使用的版本支持新的 Microsoft.Data.SqlClient 库。混合数据提供者并不有趣,应该尽可能避免。大多数流行的 NuGet 包已使用 Microsoft.Data.SqlClient。

如果您不能这样做,选项取决于您实际处理数据库异常的方式。您是否检查 SQL Server 特定的属性?

另一种选择是推迟升级,直到所有 NuGet 包也都升级为止。这两个库都包含部署期间需要包含的本机 DLL。如果混合使用库,则必须包含所有本机 DLL。

这可能会很痛苦。

处理异常情况

如果需要使用两个库,则需要单独处理每种异常类型。模式匹配使这变得更容易一些:

switch (ex) 
{
    case  System.Data.SqlClient.SqlException exc:
        HandleOldException(exc);
        return true;
    case Microsoft.Data.SqlClient.SqlException exc:
        HandleNewException(exc);
        return true;
    case DbException exc:
        HandleDbException(exc);
        return true;
    default:
        return false;
}
Run Code Online (Sandbox Code Playgroud)

映射异常

另一种选择可能是将两种异常类型映射到包含有趣属性的新自定义类型。您必须映射 和SqlExceptionSqlError。使用 AutoMapper 会让这变得更容易:

var configuration = new MapperConfiguration(cfg => {
    cfg.CreateMap<System.Data.SqlClient.SqlException, MySqlException>();
    cfg.CreateMap<System.Data.SqlClient.SqlError, MySqlError>();
    cfg.CreateMap<Microsoft.Data.SqlClient.SqlException, MySqlException>();
    cfg.CreateMap<Microsoft.Data.SqlClient.SqlError, MySqlError>();
});
Run Code Online (Sandbox Code Playgroud)

这将允许将任一异常映射到常见MySqlException类型:

var commonExp=mapper.Map<MySqlException>(ex);
Run Code Online (Sandbox Code Playgroud)

  • @Rory NuGet 包为您提供依赖项列表。如果您不使用 NuGet 包,请通过 ILSpy 打开 dll 文件,这将为您提供依赖项 (2认同)