Sunday, May 1, 2011

Mapping Error in NHibernate

Hi, I am trying to use NHibernate to connect to a Northwind database. But for some reason, I am not able to load the Entity Type.

This is my Entity class

public class Product
    {
        public virtual Int32 ProductId { get; set; }
        public virtual String Desc { get; set; }
    }

Here is my Mapping

 <class name="Product" table="Products">
    <id name="ProductId" column="ProductId" type="Int32">
      <generator class="identity"></generator>
    </id>
    <property name="Desc" column="ProductName" type="String" length="60">
    </property>
  </class>

I am getting the following error message

could not load an entity: [OracleLinq.Product#12][SQL: SELECT product0_.ProductId as ProductId0_0_, product0_.ProductName as ProductN2_0_0_ FROM Products product0_ WHERE product0_.ProductId=?]

Here is the stack Trace

   at NHibernate.Loader.Loader.LoadEntity(ISessionImplementor session, Object id, IType identifierType, Object optionalObject, String optionalEntityName, Object optionalIdentifier, IEntityPersister persister)
   at NHibernate.Loader.Entity.AbstractEntityLoader.Load(ISessionImplementor session, Object id, Object optionalObject, Object optionalId)
   at NHibernate.Loader.Entity.AbstractEntityLoader.Load(Object id, Object optionalObject, ISessionImplementor session)
   at NHibernate.Persister.Entity.AbstractEntityPersister.Load(Object id, Object optionalObject, LockMode lockMode, ISessionImplementor session)
   at NHibernate.Event.Default.DefaultLoadEventListener.LoadFromDatasource(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options)
   at NHibernate.Event.Default.DefaultLoadEventListener.DoLoad(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options)
   at NHibernate.Event.Default.DefaultLoadEventListener.Load(LoadEvent event, IEntityPersister persister, EntityKey keyToLoad, LoadType options)
   at NHibernate.Event.Default.DefaultLoadEventListener.OnLoad(LoadEvent event, LoadType loadType)
   at NHibernate.Impl.SessionImpl.FireLoad(LoadEvent event, LoadType loadType)
   at NHibernate.Impl.SessionImpl.ImmediateLoad(String entityName, Object id)
   at NHibernate.Proxy.AbstractLazyInitializer.Initialize()
   at NHibernate.Proxy.AbstractLazyInitializer.GetImplementation()
   at NHibernate.Proxy.Poco.Castle.CastleLazyInitializer.Intercept(IInvocation invocation)
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at ProductProxy4c67cf5bf6e640ab82d8c21a90e2a62b.set_Desc(String value)
   at OracleLinq.Form1.Form1_Load(Object sender, EventArgs e)

Am I doing anything wrong?

From stackoverflow
  • Is your connection string defaulting to the correct database? Check that it has Initial Catalog= [DB name here]

    Seshan : Yes. I am able to open the DB Connection. Here is the code which I am using Configuration cfg = new Configuration(); cfg.Configure(); cfg.AddAssembly(typeof(Product).Assembly); ISessionFactory sessionFactory = cfg.BuildSessionFactory(); IDbConnection conn = new SqlConnection(@"Data Source=(local);Initial Catalog=Northwind;Integrated Security=SSPI;"); ISession session = sessionFactory.OpenSession(conn); Product product = (Product)session.Load(typeof(Product), 12); product.Desc = "";
    Noel Kennedy : Have you set your HBM file to be embedded in the assembly when it gets compiled?
    Seshan : Yes i have set the Build action as embedded resource!!!
  • This should actually only be a problem when inserting, but you could also get troubles with it:

    I think "identity" is not supported by oracle, it is a SqlServer feature (an auto-counting primary key). Oracle uses sequences.

    Try the following (check the name of the sequence, which must exist)

    <id name="ProductId" column="ProductId" type="Int32">
      <generator class="sequence">
        <param name="sequence">product_seq</param>
      </generator>
    </id>
    

    Or an other id generator. Hilo or Guid are interesting alternatives. See http://barchitect.blogspot.com/2008/07/nhibernate-generator-and-primary-key.html

    Seshan : No.. The error occurs even with Sequence column in Oracle. The error occurs also in SQL Northwind database with Generator as native or identity or hilo or guid.
  • Second try:

    Here is you configuration from your comments, just for readability:

    Configuration cfg = new Configuration(); 
    cfg.Configure(); 
    cfg.AddAssembly(typeof(Product).Assembly); 
    ISessionFactory sessionFactory = cfg.BuildSessionFactory(); 
    
    IDbConnection conn = new SqlConnection(@"Data Source=(local);Initial Catalog=Northwind;Integrated Security=SSPI;"); 
    ISession session = sessionFactory.OpenSession(conn); 
    
    Product product = (Product)session.Load(typeof(Product), 12); 
    product.Desc = "";
    

    It's clear that NHibernate has the mapping file, it could not have generated the query.

    It could be that

    • the database is not there : you already checked this.
    • the table is not there : open a sql console (using the same connect string) and copy-paste the sql from the error message into it. Does it work?
    • the connection is not opened : see bollow

    I think that you need to open the connection yourself. Even better you let NHibernate create and manage the connections.

    Try this:

    Configuration cfg = new Configuration(); 
    cfg.Configure(); 
    cfg.AddAssembly(typeof(Product).Assembly); 
    ISessionFactory sessionFactory = cfg.BuildSessionFactory(); 
    
    ISession session = sessionFactory.OpenSession(); 
    
    Product product = (Product)session.Load(typeof(Product), 12); 
    product.Desc = "";
    

    the connectstring goes to the nhibernate.cfg.xml

    <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider, NHibernate</property>
    <property name="connection.connection_string">
     Data Source=(local);Initial Catalog=Northwind;Integrated Security=SSPI;
    </property>
    <property name="dialect">NHibernate.Dialect.MsSql2000Dialect</property>
    

0 comments:

Post a Comment