Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
NHibernate MSBuild Hbm2Ddl Task

I revisited porting the builtin Hbm2Ddl task from Nant to MSBuild. It's passing tests on my end and I'll take on a test drive tonight. Nothing real interesting. It is forced to copy the target assemblies into the runtime bin and then cleanup on Dispose(). NHibernate couldn't find the assemblies otherwise. Nant didn't require this but not sure what the difference is.

Here it is:

 

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
 
namespace MSBuild.Community.Tasks.NHibernate
{
    public class Hbm2Ddl : Task, IDisposable
    {
        private string _connectionProvider = "NHibernate.Connection.DriverConnectionProvider";
        private string _dialect ="NHibernate.Dialect.MsSql2005Dialect";
        private string _connectionDriverClass = "NHibernate.Driver.SqlClientDriver";
        private string _connectionString;
        private string _delimiter = " GO ";
        private bool _outputToConsole;
        private bool _exportOnly;
        private bool _dropOnly;
        private bool _formatNice;
        private ITaskItem[] _assemblies;
        private ITaskItem _outputFilename = new TaskItem("schema.sql");
        private IList<string> _assembliesToDelete = new List<string>();
        ///<summary>
        ///When overridden in a derived class, executes the task.
        ///</summary>
        ///
        ///<returns>
        ///true if the task successfully executed; otherwise, false.
        ///</returns>
        ///
        public override bool Execute()
        {
            Configuration config = new Configuration();
            IDictionary properties = new Hashtable();
            
 
            properties["connection.provider"] = ConnectionProvider;
            properties["dialect"] = Dialect;
            properties["connection.driver_class"] = ConnectionDriverClass;
            properties["connection.connection_string"] = ConnectionString;
 
            config.AddProperties(properties);
 
            foreach (ITaskItem item in Assemblies)
            {
                string filePath = item.ItemSpec;
                Log.LogMessageFromText(string.Format("Adding assembly file {0}", filePath), MessageImportance.Normal);
                try
                {
                    string fileName = Path.GetFileName(filePath);
                    string target = Path.Combine(AssemblyDirectory, fileName);
                    Log.LogMessageFromText(string.Format("Copying {0} to {1}", filePath, target),MessageImportance.High);
                    File.Copy(filePath, target, true);
                    AssemblyName an = AssemblyName.GetAssemblyName(target);
                    Assembly asm = Assembly.Load(an);
                    config.AddAssembly(asm);
                    _assembliesToDelete.Add(target);
                    
                }
                catch (Exception e)
                {
                    Log.LogMessageFromText(string.Format("Error loading assembly {0}. Be sure the target assembly is in the \bin with NHibernate (if the copy failed).", filePath),
                        MessageImportance.High);
                    
                    return false;
                }
            }
            string outputFilename = OutputFilename.ItemSpec;
            SchemaExport se = new SchemaExport(config);
            if (!IsStringNullOrEmpty(outputFilename))
            {
                se.SetOutputFile(outputFilename);
            }
            se.SetDelimiter(Delimiter);
            Log.LogMessageFromText( "Exporting ddl schema.", MessageImportance.Normal);
 
            se.Execute(OutputToConsole, ExportOnly, DropOnly, FormatNice);
 
            if (!IsStringNullOrEmpty(outputFilename))
            {
                Log.LogMessageFromText(string.Format("Successful DDL schema output: {0}", OutputFilename), MessageImportance.High);
            }
            return true;
        }
        private void CleanUp()
        {
            
            foreach (string asmToDelete in _assembliesToDelete)
            {
                Log.LogMessageFromText(string.Format("Deleting {0}", asmToDelete), MessageImportance.High);
                File.Delete(asmToDelete);
            }
        }
        private static bool IsStringNullOrEmpty(string input)
        {
            return (input == null || input.Length == 0);
        }
        /// <summary>
        /// Gets or sets the connection provider.  NHibernate.Connection.DriverConnectionProvider is the default
        /// </summary>
        /// <value>The connection provider.</value>
        public string ConnectionProvider
        {
            get { return this._connectionProvider; }
            set { this._connectionProvider = value; }
        }
        public string AssemblyCodeBase
        {
            get { return Assembly.GetExecutingAssembly().CodeBase; }
        }
 
        public string AssemblyDirectory
        {
            get { return new Uri(Path.GetDirectoryName(AssemblyCodeBase)).AbsolutePath; }
        }
        
 
        /// <summary>
        /// Gets or sets the dialect.  NHibernate.Dialect.MsSql2005Dialect is the default
        /// </summary>
        public string Dialect
        {
            get { return this._dialect; }
            set { this._dialect = value; }
        }
 
        /// <summary>
        /// Gets or sets the connection driver class. NHibernate.Driver.SqlClientDriver is the default.
        /// </summary>
        /// <value>The connection driver class.</value>
        public string ConnectionDriverClass
        {
            get { return this._connectionDriverClass; }
            set { this._connectionDriverClass = value; }
        }
 
        /// <summary>
        /// Gets or sets the connection string used to access the ddl.
        /// </summary>
        /// <value>The connection string.</value>
        [Required]
        public string ConnectionString
        {
            get { return this._connectionString; }
            set { this._connectionString = value; }
        }
 
        /// <summary>
        /// Gets or sets the delimiter.  GO is the default.
        /// </summary>
        public string Delimiter
        {
            get { return this._delimiter; }
            set { this._delimiter = value; }
        }
 
        /// <summary>
        /// Gets or sets a value indicating whether the schema should be outputted to the console
        /// </summary>
        /// <value><see langword="true" /> to output to the console; otherwise, <see langword="false" />.</value>
        public bool OutputToConsole
        {
            get { return this._outputToConsole; }
            set { this._outputToConsole = value; }
        }
 
        /// <summary>
        /// Gets or sets a value indicating whether the schema ddl script should only be exported
        /// or if it should be executed on the database server.
        /// </summary>
        /// <value><see langword="true" /> if only output the script; otherwise, <see langword="false" /> - Execute the script on the db server.</value>
        public bool ExportOnly
        {
            get { return this._exportOnly; }
            set { this._exportOnly = value; }
        }
 
        /// <summary>
        /// Gets or sets a value indicating whether only the drop script should be executed
        /// </summary>
        /// <value><see langword="true" /> if only drop objects; otherwise, <see langword="false" /> - Drop and Create objects.</value>
        public bool DropOnly
        {
            get { return this._dropOnly; }
            set { this._dropOnly = value; }
        }
 
        /// <summary>
        /// Gets or sets a value indicating whether the ddl script should be formatted nicely
        /// </summary>
        /// <value><see langword="true" /> for nice format; otherwise, <see langword="false" /> - One statement per line.</value>
        public bool FormatNice
        {
            get { return this._formatNice; }
            set { this._formatNice = value; }
        }
 
        /// <summary>
        /// Gets or sets the filename to write the ddl schema script to. Default is 'schema.sql'.
        /// </summary>
        /// <value>The output filename.</value>
        public ITaskItem OutputFilename
        {
            get { return this._outputFilename; }
            set { this._outputFilename = value; }
        }
 
        /// <summary>
        /// Gets or sets the assemblies load with embedded *.hbm.xml resources.
        /// </summary>
        /// <value>The assemblies.</value>
        [Required]
        public ITaskItem[] Assemblies
        {
            get { return _assemblies; }
            set { _assemblies = value; }
        }
 
        #region IDisposable Members
 
        #endregion
 
        ///<summary>
        ///Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        ///</summary>
        ///<filterpriority>2</filterpriority>
        public void Dispose()
        {
            CleanUp();
        }
    }
}

 

And here is the MSBuild usage:

<PropertyGroup>
  <ConnectionString>Server=localhost;Integrated Security=True</ConnectionString>
  <OutputFilename>$(testdir)\schema.sql</OutputFilename>
  <ExportOnly>true</ExportOnly>    
</PropertyGroup>
 
<ItemGroup>
  <inputAssemblies Include="$(testdir)\A.dll"/>    
</ItemGroup>
 
<Target Name="Hbm2Ddl">
  <Message Text="Firing Hbm2Ddl" />
  <Hbm2ddl ConnectionString="Server=localhost;Integrated Security=True"
           OutputFilename="$(testdir)/schema.sql" Assemblies="@(inputAssemblies)"/>
</Target>

 

I'm not sure if this should be submitted to the Community Tasks or not. I included it in my copy of their source for testing.


Posted 10-25-2007 4:15 PM by Michael Nichols
Filed under: ,

[Advertisement]

Comments

IDisposable Thoughts wrote Generating the NHibernate Database Schema with a MSBuild Task
on 02-19-2009 1:00 AM

Generating the NHibernate Database Schema with a MSBuild Task

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)