2013-09-25 24 views
3

我想抓住违反UNIQUE KEY约束,插入一行,但不知道如何。流利的NHibernate,正确的方式来实现ISQLExceptionConverter

  1. RDBMS - MSSQL Server 2008的
  2. NHibernate的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 
     } 
    } 

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

+0

这将做的工作: http://stackoverflow.com/questions/5393044/catch-sqlexception-when-attempting-nhibernate-transaction/5393080 –

回答

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; 
    } 
} 
+2

谢谢。问题在于例外编号,我遇到了一个错误的例外。来自我的啤酒! (握手) –

+0

我不得不赞同以啤酒为主题的评论 –