From: Chris M. <cm...@us...> - 2006-07-27 05:45:22
|
User: cmicali Date: 06/07/26 19:08:19 Modified: etc/andromda-dotnet/AndroMDA.NHibernateSupport/src DbSupport.cs DefaultSessionManager.cs Log: - Added eric's support code for the new SchemaExport Revision Changes Path 1.2 +255 -4 plugins/etc/andromda-dotnet/AndroMDA.NHibernateSupport/src/DbSupport.cs Index: DbSupport.cs =================================================================== RCS file: /cvsroot/andromdaplugins/plugins/etc/andromda-dotnet/AndroMDA.NHibernateSupport/src/DbSupport.cs,v retrieving revision 1.1 retrieving revision 1.2 diff -u -w -r1.1 -r1.2 --- DbSupport.cs 9 Jul 2006 12:08:21 -0000 1.1 +++ DbSupport.cs 27 Jul 2006 02:08:19 -0000 1.2 @@ -1,12 +1,23 @@ // Name: DbSupport.cs // Author: Naresh Bhatia - using System; +using System.Configuration; +using System.Data; +using System.IO; +using log4net; +using NHibernate; namespace AndroMDA.NHibernateSupport { - public class DbSupport + /// <summary> + /// Contains methods supporting the generation of tables based on NHibernate mappings. + /// </summary> + public class DbSupport : IDisposable { + private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + #region Public static methods + /// <summary> /// Creates ddl and/or runs it against the database. /// </summary> @@ -18,5 +29,245 @@ new NHibernate.Tool.hbm2ddl.SchemaExport(SessionManagerFactory.SessionManager.Config); schemaExport.Create(script, export); } + + #endregion + + #region Public instance methods + /// <summary> + /// Generates DDL for the target database to create the tables. + /// </summary> + /// <returns>An array of strings containing the DDL.</returns> + public string[] GenerateCreateSQL() + { + NHibernate.Dialect.Dialect dialect = NHibernate.Dialect.Dialect.GetDialect(SessionManagerFactory.SessionManager.Config.Properties); + string[] createSql = SessionManagerFactory.SessionManager.Config.GenerateSchemaCreationScript(dialect); + return createSql; + } + + /// <summary> + /// Generates DDL for the target database to drop the tables. + /// </summary> + /// <returns>An array of strings containing the DDL.</returns> + public string[] GenerateDropSQL() + { + NHibernate.Dialect.Dialect dialect = NHibernate.Dialect.Dialect.GetDialect(SessionManagerFactory.SessionManager.Config.Properties); + string[] dropSql = SessionManagerFactory.SessionManager.Config.GenerateDropSchemaScript(dialect); + return dropSql; + } + + /// <summary> + /// Regenerates the database. + /// </summary> + /// <param name="createFile">The create file.</param> + /// <param name="dropFile">The drop file.</param> + /// <returns></returns> + public string RegenerateDatabase(string createFile, string dropFile) + { + return RegenerateDatabase(new FileInfo(createFile), new FileInfo(dropFile)); + } + + /// <summary> + /// This method can be used to regenerate a database schema using NHibernate. + /// It can be run multiple times and can delete the old schema, even if your + /// mapping files have changed the schema since the last time it was run. + /// </summary> + /// <param name="createFile">The <see cref="FileInfo"/> object containing the + /// 'create schema' DDL commands. This file does not have to exist.</param> + /// <param name="dropFile">The <see cref="FileInfo"/> object containing the + /// previously generated 'drop schema' DDL commands. This file does not + /// have to exist.</param> + /// <returns>The DDL used to create the tables.</returns> + public string RegenerateDatabase(System.IO.FileInfo createFile, System.IO.FileInfo dropFile) + { + string dropScriptFileName = null; + string dropSQL = null; + bool errorWhileExporting = false; + + if (createFile == null) + throw new ArgumentNullException("createFile", "The create FileInfo object can't be null."); + + if (dropFile == null) + throw new ArgumentNullException("dropFile", "The drop FileInfo object can't be null."); + + //read in the "Delete Statements SQL" script, if it exists. + if (dropFile.Exists) + { + // First, copy this to the 'old drop' file + string oldFile = Path.GetFileNameWithoutExtension(dropFile.Name) + "-old" + dropFile.Extension; + File.Copy(dropFile.FullName, oldFile, true); + + // Next, read the contents of the file + try + { + using (System.IO.TextReader reader = dropFile.OpenText()) + { + dropSQL = reader.ReadToEnd(); + reader.Close(); + } + } + catch (Exception ex) + { + string errMsg = "An error occurred while opening the delete script. Continuing the schema export process anyway."; + log.Error(errMsg, ex); + } + } + else + { + // Create an empty drop file since we are continuing, but we did + // not drop anything + FileStream fs = File.Create(dropFile.FullName); + fs.Close(); + fs = null; + } + + IDbConnection conn = SessionManagerFactory.SessionManager.Session.Connection; + string[] dropSQLArray; + string[] createDBArray; + + using (IDbCommand command = conn.CreateCommand()) + { + // Execute the SQL script to drop the current schema + if (dropSQL != null && dropSQL.Trim().Length > 0) + { + command.CommandText = dropSQL; + command.CommandType = CommandType.Text; + + try + { + command.ExecuteNonQuery(); + + if (log.IsInfoEnabled) + log.Info("Dropped the current schema using the following SQL:" + Environment.NewLine + dropSQL); + } + catch (Exception ex) + { + log.Error("An error occured while trying to drop the existing database schema.", ex); + throw; + } + } + + // Now generate the 'drop sql' script for the new database schema + dropSQLArray = GenerateDropSQL(); + + // Now generate the 'create sql' script for the new database schema + createDBArray = GenerateCreateSQL(); + + // Run the create SQL code + SessionManagerFactory.SessionManager.BeginTransaction(); + foreach (string sql in createDBArray) + { + command.CommandText = sql; + command.CommandType = CommandType.Text; + SessionManagerFactory.SessionManager.Session.Transaction.Enlist(command); + try + { + command.ExecuteNonQuery(); + } + catch (Exception ex) + { + errorWhileExporting = true; + log.Error("An error occured while running the create script.", ex); + } + } + + if (errorWhileExporting) + SessionManagerFactory.SessionManager.RollbackTransaction(); + else + SessionManagerFactory.SessionManager.CommitTransaction(); + + } + + // Save the create script + try + { + if (createFile.Exists) + { + createFile.Delete(); + createFile.Refresh(); + } + using (StreamWriter sw = createFile.CreateText()) + { + foreach (string sql in createDBArray) + { + sw.WriteLine(sql); + } + sw.Close(); + } + } + catch (Exception ex) + { + log.Error(String.Format("A problem occurred while creating the {0} file containing the CREATE DDL.", createFile.FullName), ex); + } + + // Save the delete script so we can use it the next time + try + { + //If we had errors while creating the + //schema, then save the new 'drop schema' sql script to a new file + if (errorWhileExporting && dropFile != null) + { + //otherwise, save the old 'Delete' script and create the delete script with a new name. + dropScriptFileName = System.IO.Path.GetFileNameWithoutExtension(dropFile.FullName) + ".failure" + dropFile.Extension; + } + else + dropScriptFileName = dropFile.FullName; + + // Remove the reference to the dropFile + dropFile = null; + + using (System.IO.StreamWriter writer = File.CreateText(dropScriptFileName)) + { + foreach (string sqlLine in dropSQLArray) + { + writer.WriteLine(sqlLine); + } + } + log.Info(String.Format("The delete DDL was written to {0}", dropScriptFileName)); + + if (errorWhileExporting) + { + throw new ApplicationException("There were errors while exporting the schema to the database. Please review the log for more detailed error information."); + } + } + catch (Exception ex) + { + string msg = "Unable to create the '{0}' "+ + "removal script. This means that, if the schema changes the next time you "+ + "run SchemaExport, it's likely we won't be able to remove the existing tables " + + "because not all the constraints will be removed."; + log.Error(String.Format(msg, dropScriptFileName), ex); + throw new ApplicationException(String.Format(msg, dropScriptFileName), ex); + } + + return String.Join(Environment.NewLine, createDBArray); + + } + + #endregion + + #region Constructor + + public DbSupport() + { + log4net.Config.XmlConfigurator.Configure(); + + // Start NHibernate + SessionManagerFactory.SessionManager.HandleApplicationStart(); + SessionManagerFactory.SessionManager.HandleSessionStart(); + } + + #endregion + + #region IDisposable Members + + public void Dispose() + { + //Stop NHibernate + SessionManagerFactory.SessionManager.HandleSessionEnd(); + SessionManagerFactory.SessionManager.HandleApplicationEnd(); + } + + #endregion + } } \ No newline at end of file 1.2 +4 -9 plugins/etc/andromda-dotnet/AndroMDA.NHibernateSupport/src/DefaultSessionManager.cs Index: DefaultSessionManager.cs =================================================================== RCS file: /cvsroot/andromdaplugins/plugins/etc/andromda-dotnet/AndroMDA.NHibernateSupport/src/DefaultSessionManager.cs,v retrieving revision 1.1 retrieving revision 1.2 diff -u -w -r1.1 -r1.2 --- DefaultSessionManager.cs 9 Jul 2006 12:08:21 -0000 1.1 +++ DefaultSessionManager.cs 27 Jul 2006 02:08:19 -0000 1.2 @@ -190,12 +190,7 @@ // will attempt to be initialized if it is null if (SessionFactory == null) { - throw new Exception("The nhibernate session factory has not been initialized."); - } - - if (GetSession() != null) - { - throw new Exception("A Session already exists."); + throw new Exception("SessionStart was called but the nhibernate session factory has not been initialized."); } if (!isSessionInitializedLazily) { @@ -206,14 +201,14 @@ public void HandleSessionEnd() { if (GetTransaction() != null) - throw new Exception("A transaction still exists."); + throw new Exception("SessionEnd was called but a transaction still exists."); CloseSession(); } public void BeginTransaction() { if (GetTransaction() != null) - throw new Exception("A transaction already exists."); + throw new Exception("BeginTransaction was called but a transaction already exists."); ITransaction transaction = Session.BeginTransaction(); SetTransaction(transaction); @@ -253,7 +248,7 @@ } catch (Exception e) { - throw new Exception("An error occured while attempting to load nhibernate.cfg", e); + throw new Exception("An error occured while attempting to load nhibernate.config", e); } } else if (SettingExists("hibernate.dialect", nhibernateConfig)) |