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
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>();
        ///When overridden in a derived class, executes the task.
        ///true if the task successfully executed; otherwise, false.
        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;
            foreach (ITaskItem item in Assemblies)
                string filePath = item.ItemSpec;
                Log.LogMessageFromText(string.Format("Adding assembly file {0}", filePath), MessageImportance.Normal);
                    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);
                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),
                    return false;
            string outputFilename = OutputFilename.ItemSpec;
            SchemaExport se = new SchemaExport(config);
            if (!IsStringNullOrEmpty(outputFilename))
            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);
        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>
        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>
        public ITaskItem[] Assemblies
            get { return _assemblies; }
            set { _assemblies = value; }
        #region IDisposable Members
        ///Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        public void Dispose()


And here is the MSBuild usage:

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


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: ,



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

Google Reader or Homepage Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of
Red-Gate Tools For SQL and .NET


SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
NHibernate Profiler
Balsamiq Mockups
JetBrains - ReSharper
Web Sequence Diagrams
Ducksboard<-- NEW Friend!


Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers


Community Server (Commercial Edition)