views:

45

answers:

3

I'd like to use the new VS2010 web.config transformation feature to change the connection string within the nhibernate configuration in my web.config file. The relevant snippet is something like this:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="hibernate-configuration" type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />
  </configSections>

  <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <session-factory>
      <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
      <property name="connection.driver_class">NHibernate.Driver.OracleDataClientDriver</property>
      <property name="connection.connection_string">(test connection string)</property>
      <property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
...

I've tried the following transformation without success:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"&gt;
    <hibernate-configuration  xmlns="urn:nhibernate-configuration-2.2" >
        <session-factory>
            <property name="connection.connection_string" xdt:Transform="Replace">(production connection string)</property>
        </session-factory>
    </hibernate-configuration>
</configuration>

The problem seems to be in the xmlns attribute of the nhibernate-configuration element.

What should be the correct transformation to replace (test connection string) with (production connection string) during deployment?

A: 

Since session-factory contains a collection of child elements, you need to tell it which child to replace using the Match locator.

<?xml version="1.0"?>
    <configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"&gt;
        <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
            <session-factory>
                <property name="connection.connection_string" xdt:Transform="Replace" xdt:Locator="Match(name)>(production connection string)</property>
            </session-factory>
        </hibernate-configuration>
    </configuration>
Kiff
I have already tried that, but the transformation step cannot even locate the "hibernate-configuration" node... very likely due to its xmlns attribute.
gschuager
I know I'm grasping at straws here, but the last thing that I would try before giving up would be to eliminate that extra white space in the hibernate-configuration element so that the configs match up exactly. I've edited my code above to reflect what I'm talking about.
Kiff
A: 

The answer may be a bit late, but since I needed this as well, I figured I would post an answer that worked for me in the event anyone else stumbles upon this question.

You need to use the xdt:Locator in combination with an xpath expression to get the correct node. So something like this should work.

<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
   <session-factory>
      <property name="connection.connection_string" xdt:Locator="XPath(//*[local-name()='hibernate-configuration']//*[local-name()='property'][@name='connection.connection_string'])" xdt:Transform="Replace">(production connection string)</property>
   </session-factory>
</hibernate-configuration>

There may be a better xpath expression, but this is what worked for me.

The only issue, which isn't that big a deal, is the replaced node will have a namespace redeclared on the node. So the replaced node will actually look like this in the final output.

<property name="connection.connection_string" xmlns="urn:nhibernate-configuration-2.2">(production connection string)</property>
bgrebil
A: 

I recently encountered the same issue - it was solved by placing explicit namespace prefixes in the transform file

<configuration
               xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform"
               xmlns:hib="urn:nhibernate-configuration-2.2"
              >
    <hib:hibernate-configuration>
        <hib:session-factory>
            <hib:property name="connection.connection_string" xdt:Transform="Replace">(production connection string)</hib:property>
        </hib:session-factory>
    </hib:hibernate-configuration>
</configuration>

The resulting transformed web.config file was thankfully free of the namespace prefixes (i.e. it left the nhibernate namespace declaration in the same spot as it was in the original web.config file and correctly named all the nodes)

Andrew Patterson