流畅的NHibernate,正确的方式来实现ISQLExceptionConverter

时间:2013-09-25 16:13:46

标签: c# nhibernate exception-handling fluent-nhibernate

我想在插入行时捕获违反UNIQUE KEY约束,但不知道如何。

  1. RDBMS - MSSQL Server 2008
  2. NHibernate 3.3版本
  3. NHibernate配置

    public NHibernate.Cfg.Configuration GetConfiguration()
        {
            string connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionSqlServer"].ConnectionString;
            var cfg = Fluently.Configure()
                              .Database(MsSqlConfiguration.MsSql2008
                              .ConnectionString(connectionString)
                              .ShowSql()
                              .Driver<NHibernate.Driver.Sql2008ClientDriver>()
                              .Provider<NHibernate.Connection.DriverConnectionProvider>()
                              .Dialect<NHibernate.Dialect.MsSql2008Dialect>())
                              .Mappings(m => m.FluentMappings.AddFromAssemblyOf<EntityBase>().Conventions.Add(DynamicUpdate.AlwaysTrue()))
                              .ExposeConfiguration(config =>
                                  {
                                      config.SetInterceptor(new SqlStatementInterceptor());
                                      config.SetProperty(Environment.SqlExceptionConverter,
                                          typeof(MsSqlExceptionConverter).AssemblyQualifiedName);
                                      config.Properties[Environment.CurrentSessionContextClass] = "web";
                                      var schemaUpdate = new SchemaUpdate(config);
                                          schemaUpdate.Execute(false, true);
                                  })
                              .BuildConfiguration();
            return cfg;
        }
    

    ISQLExceptionConverter 实施:

    public class MsSqlExceptionConverter : ISQLExceptionConverter
    {
        public Exception Convert(AdoExceptionContextInfo exInfo)
        {
            var sqle = ADOExceptionHelper.ExtractDbException(exInfo.SqlException) as SqlException;
            if (sqle != null)
            {
                switch (sqle.Number)
                {
                    case 547:
                        return new ConstraintViolationException(exInfo.Message,
                            sqle.InnerException, exInfo.Sql, null);
                    case 208:
                        return new SQLGrammarException(exInfo.Message,
                            sqle.InnerException, exInfo.Sql);
                    case 3960:
                        return new StaleObjectStateException(exInfo.EntityName, exInfo.EntityId);
                }
            }
            return SQLStateConverter.HandledNonSpecificException(exInfo.SqlException,
                exInfo.Message, exInfo.Sql);
        }
    }
    

    try-catch 声明:

    public void InsertCultures()
        {
            using (var uow = _unitOfWorkFactory.Create())
            {
                var CULTURE_DEFAULTS = new List<Culture>()
                {
                    new Culture() {Symbol = "ro-RO", Language = "Romana"},
                    new Culture() {Symbol = "ru-RU", Language = "Rusa"},
                    new Culture() {Symbol = "en-US", Language = "Engleza"}
                };
    
                foreach (var culture in CULTURE_DEFAULTS)
                {
                    try
                    {
                        _cultureRepository.Create(culture);
                    }
                    catch (ConstraintViolationException e)
                    {
    
                    }
    
                }
               /// Other stuff
            }
        }
    

    如果有人有鹰眼请分享:)谢谢!

1 个答案:

答案 0 :(得分:4)

这是我工作的非本地化版本,用于捕获唯一的密钥违规,希望它有所帮助。我抛出一个自定义的UniqueKeyException,调用代码可以捕获和处理。您的Fluent配置代码对我来说是正确的。

public class SqlServerExceptionConverter : ISQLExceptionConverter
{
    public Exception Convert(AdoExceptionContextInfo adoExceptionContextInfo)
    {
        var sqlException = adoExceptionContextInfo.SqlException as SqlException;
        if (sqlException != null)
        {
            // 2601 is unique key, 2627 is unique index; same thing: 
            // http://blog.sqlauthority.com/2007/04/26/sql-server-difference-between-unique-index-vs-unique-constraint/
            if (sqlException.Number == 2601 || sqlException.Number == 2627)
            {
                return new UniqueKeyException(sqlException.Message, sqlException);
            }
        }
        return adoExceptionContextInfo.SqlException;
    }
}