Nhibernate 数据库独立错误处理

Nhibernate data base independent error handling

试图为我的最后一个问题 () 找到解决方案,我决定用我自己的自定义错误包装所有异常。到目前为止,这是我的代码:

    public Exception Convert(NHibernate.Exceptions.AdoExceptionContextInfo exInfo)
    {
        var sqle = (System.Data.SQLite.SQLiteException)exInfo.SqlException;
        var errorDescription = exInfo.SqlException.Message.ToString();
        if (sqle != null)
        {
            //Definition of error codes (for SQLite) to catch and handle
            switch (sqle.ErrorCode)
            {
                //Most possible error in our project: case 19
                case 19:
                    return new ConstraintViolationException(exInfo.Message,
                        sqle.InnerException);
                case 5:
                    return new DbLockedException();
                case 6:
                    return new TableLockedException();
                case 8:
                    return new ReadOnlyDbException();
                case 9:
                    return new InterruptException();
                case 10:
                    return new IOException();
                case 11:
                    return new DbCorruptException();

我从这里遵循了自定义异常的想法:Returning a custom exception

现在我遇到一个问题:

因为我们使用的是 NHibernate。我们希望保持我们的代码数据库独立。使用您可以看到的代码,它只适用于 SQLite。

如果你想让你的程序、数据库独立,代码错误不是一个好主意,因为每个数据库都有自己的代码错误和异常。

感谢您的提醒!

我将依赖于数据库的设置封装在专用程序集中:

  • MyApplication.Data.SqlLite
  • MyApplication.Data.Oracle

每个程序集包含一组 类 实现通用接口以放入通用程序集。在你的情况下,我会创建一个名为 DbExceptionConverter 的接口,并在它们的程序集中实现。在应用程序开始时,我会在容器中注册正确的实现。

你也可以把它们都放在一个抽象工厂里。

好吧,我最后的做法是:

1- 我保留了 ORM 项目,因为它实际上并不需要任何特定的数据库引用或配置(驱动程序等)(程序集将知道 hibernate.cfg.xml 使用哪个驱动程序文件)

2- 正如@onof 所说,我创建了一个 DbExceptionConverter 程序集,其中包含所有与数据库相关的设置以及我想使用的每个数据库的例外情况。每个 class 用自己的代码包装异常。

我在这里的问题是:"Now, how do I load the custom DbExceptionHandler?" 好吧,我只是使用 "hibernate.cfg.xml" 文件中的 sql_exception_converter 属性 字段,如下所示:

对于 SQLite:(注意 sql_exception_converter 属性)

<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>
    <property name="adonet.batch_size">5000</property>
    <property name="connection.driver_class">NHibernate.Driver.SQLite20Driver</property>
    <property name="connection.connection_string">Data Source=DBFile.db;Version=3;New=True;UseUTF8Encoding=True;</property>
    <property name="sql_exception_converter">DbExceptionConverter.SQLiteExceptionHandler.SqlExceptionConverter, DbExceptionConverter</property>
    <property name="dialect">NHibernate.Dialect.SQLiteDialect</property>
  </session-factory>
</hibernate-configuration>

对于 Postgres:(注意 sql_exception_converter 属性)

<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>
    <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
    <property name="dialect">NHibernate.Dialect.PostgreSQLDialect</property>
    <property name="connection.driver_class">NHibernate.Driver.NpgsqlDriver</property>
    <property name="connection.connection_string">Server=127.0.0.1;Port=5432;Database=DbName;User Id=postgres;Password=postgres;</property>
    <property name="sql_exception_converter">DbExceptionConverter.PostgresExceptionHandler.SqlExceptionConverter, DbExceptionConverter</property>
  </session-factory>
</hibernate-configuration>

3- 在每个sql_exception_converter 属性中,你可以看到我使用了class的命名空间和class名称来告诉程序集哪个异常处理程序使用。

事实证明这很容易,我希望我可以用我的经验帮助其他人。

如果有人有任何想法、建议,或者认为这不是一个好主意,我会很高兴听到。