views:

641

answers:

3

Hi All,

I tried an example from NHibernate in Action book and when I try to run the app, it throws an exception saying "Could not compile the mapping document:

HelloNHibernate.Employee.hbm.xml"

Below is my code,

Employee.hbm.xml

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="HelloNHibernate.Employee, HelloNHibernate" lazy="false" table="Employee">
<id name="id" access="field">
  <generator class="native"/>
</id>
<property name="name" access="field" column="name"/>
<many-to-one access="field" name="manager" column="manager" cascade="all"/>
</class>
</hibernate-mapping>

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using System.Reflection;
using NHibernate.Cfg;

namespace HelloNHibernate
{
class Program
{
    static void Main(string[] args)
    {
        CreateEmployeeAndSaveToDatabase();
        UpdateTobinAndAssignPierreHenriAsManager();
        LoadEmployeesFromDatabase();

        Console.WriteLine("Press any key to exit...");
        Console.ReadKey();
    }

    static void CreateEmployeeAndSaveToDatabase()
    {
        Employee tobin = new Employee();
        tobin.name = "Tobin Harris";

        using (ISession session = OpenSession())
        {
            using (ITransaction transaction = session.BeginTransaction())
            {
                session.Save(tobin);
                transaction.Commit();
            }
            Console.WriteLine("Saved Tobin to the database");
        }
    }

    static ISession OpenSession()
    {
        if (factory == null)
        {
            Configuration c = new Configuration();
            c.AddAssembly(Assembly.GetCallingAssembly());
            factory = c.BuildSessionFactory();
        }
        return factory.OpenSession();
    }

    static void LoadEmployeesFromDatabase()
    {
        using (ISession session = OpenSession())
        {
            IQuery query = session.CreateQuery("from Employee as emp order by emp.name asc");

            IList<Employee> foundEmployees = query.List<Employee>();

            Console.WriteLine("\n{0} employees found:", foundEmployees.Count);

            foreach (Employee employee in foundEmployees)
                Console.WriteLine(employee.SayHello());
        }
    }

    static void UpdateTobinAndAssignPierreHenriAsManager()
    {
        using (ISession session = OpenSession())
        {
            using (ITransaction transaction = session.BeginTransaction())
            {
                IQuery q = session.CreateQuery("from Employee where name='Tobin Harris'");

                Employee tobin = q.List<Employee>()[0];
                tobin.name = "Tobin David Harris";

                Employee pierreHenri = new Employee();
                pierreHenri.name = "Pierre Henri Kuate";

                tobin.manager = pierreHenri;
                transaction.Commit();

                Console.WriteLine("Updated Tobin and added Pierre Henri");
            }
        }
    }

    static ISessionFactory factory;
}
}

Employee.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HelloNHibernate
{
class Employee
{
    public int id;
    public string name;
    public Employee manager;

    public string SayHello()
    {
        return string.Format("'Hello World!', said {0}.", name);
    }
}
}

App.config

    <?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.3300.0, Culture=neutral
             PublicKeyToken=b77a5c561934e089"/>
  </configSections>
  <nhibernate>
    <add key="hibernate.show_sql" value="false"/>
    <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider"/>
    <add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2005Dialect"/>
    <add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver"/>
    <add key="hibernate.connection.connection_string" value="Server=(local)\SQLEXPRESS; Database=HelloNHibernate;Integrated Security=SSPI;"/>
  </nhibernate>
</configuration>
A: 

Do you have a manager class and mapping defined? The

<many-to-one access="field" name="manager" column="manager" cascade="all"/>

line is looking for one. If the "manager" field is supposed to be an Employee, then you probably want:

<many-to-one access="field" name="manager" column="manager" class="HelloNHibernate.Employee, HelloNHibernate" cascade="all"/>

Benjamin Geiger
No manager is only a field in table Employee. So I tried changing the line to simple <property name="manager" access="field" column="manager"/>but now I get the below error.Could not compile the mapping document: HelloNHibernate.Employee.hbm.xml
developer
I also tried using the above line that you have posted but I still get that error.
developer
Also I am using NHibernate 1.2 version..
developer
A: 

I think I see the problem now. The problem appears to be in this line:

<add key="hibernate.connection.connection_string" value="SQL2008EXPRESS" Database="HelloNHibernate;Integrated Security=SSPI;User Id=SQL2008"/>

The connection string is malformed, and it's throwing off the XML parser. Since the "value" attribute ends early, the XML parser thinks "Database=" is another XML attribute, but it's not one it recognizes, so it chokes. The solution is to fix the connection string.

The line should probably read:

<add key="hibernate.connection.connection_string" value="Server=(local)\SQLEXPRESS; Database=HelloNHibernate;Integrated Security=SSPI;"/>

This is assuming you're using Windows authentication; given that this is a learning project, that's probably the best way to go. If you're using SQL Server authentication, use this line instead:

<add key="hibernate.connection.connection_string" value="Server=(local)\SQLEXPRESS; Database=HelloNHibernate; User Id=theusername; Password=thepassword"/>

An aside: I don't think NHibernate 1.2.1GA has a SQL Server 2008 dialect. Instead, use NHibernate.Dialect.MsSql2005Dialect.

Benjamin Geiger
I am using windows authentication and I tried changing App.config to above edited file, and now I get error that says 'The type initializer for 'NHibernate.Cfg.Environment' threw an exception'. This is so confusing..
developer
Does it include an inner exception? That'd be more useful for diagnosing the problem.
Benjamin Geiger
Below is the inner exception detail {"An error occurred creating the configuration section handler for nhibernate: The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047) (C:\\My Documents\\Visual Studio 2008\\Projects\\HelloNHibernate\\HelloNHibernate\\HelloNHibernate\\bin\\Debug\\HelloNHibernate.vshost.exe.Config line 4)"}
developer
+1  A: 

Let's open the Matryoshka doll a bit further, and solve the other problem:

In this line:

<section name="nhibernate" type="System.Configuration.NameValueSectionHandler, System, Version=1.0.3300.0, Culture=neutral PublicKeyToken=b77a5c561934e089"/>

you're missing a comma between "neutral" and "PublicKeyToken".

Give that a try.

Benjamin Geiger
I changed it to the above line and now it gives the below error,Could not compile the mapping document: HelloNHibernate.Employee.hbm.xmlwhich it gave previously..
developer
Hey, it worked after I changed the manager field mapping from property to many-to-one.Thanks a lot for all your help:)
developer

related questions