NHibernate Mapping Problem - Can I Map Multiple Assemblies? - nhibernate

I have the following mapping file:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="Project1.Accounts"
namespace="Project1.Core.Domain">
<class name="Equipment" table="Equipment">
<id name="ID" column="ID">
<generator class="identity"></generator>
</id>
<property name="Name" />
<property name="Description" />
<property name="AccountID" />
<property name="EquipmentTypeID" />
<many-to-one name="Account" class="Project2.Core.Domain.Account, Project2.Core" column="AccountID"/>
<many-to-one name="EquipmentType" class="Insight.IT.Accounts.Core.Domain.EquipmentType, Insight.IT.Accounts" column="EquipmentTypeID"/>
</class>
</hibernate-mapping>
I'm getting the following error:
NHibernate.MappingException: An association from the table Equipment refers to an unmapped class: Project2.Domain.Account
Just to be clear - The Account class lives in a different assembly than the Equipment class does. The project that the Account class resides in has it's own hibernate.cfg.xml.
Basically, it looks like i need a way to reference multiple mapping assemblies in the hibernate.cfg.xml file. Is this possible??

You can do it like this:
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory>
<property name="dialect">...</property>
<property name="connection.driver_class">...</property>
...
<mapping assembly="MyProject.OtherAssembly"/>
</session-factory>
</hibernate-configuration>

It is possible, you'll just have to indicate this in your mapping file (and it looks like you did this).
Did you add both the assemblies to the NHibernate configuration, before creating the sessionfactory ?

Thanks for the responses. Actually, I ended up doing it a little different. I just removed the tag from the hibernate.cfg and used fully qualified names in the .hbm.xml files. Thanks!!

Related

Lazy load a self-referencing table

I'm trying to map a self-referencing table with NHibernate 3.2.0.4000. However, whenever I get an instance of DomainObject, it eagerly loads the subsequent versions. I'd rather not have to put an extra column my table, though that is an option.
Can I have NHiberante not eagerly load all of the subsequent versions without maintaining the relationship on both sides?
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping assembly="NHibernateHierarchyTest" namespace="NHibernateHierarchyTest" xmlns="urn:nhibernate-mapping-2.2">
<class name="DomainObject" table="DOMAIN_OBJECT" lazy="true" >
<id name="DomainObjectId" column="DOMAIN_OBJECT_ID">
<generator class="identity" />
</id>
<property name="Property">
<column name="PROPERTY" />
</property>
<many-to-one name="PreviousVersion" class="DomainObject" >
<column name="PREVIOUS_VERSION_DOMAIN_OBJECT_ID" />
</many-to-one>
<!--<many-to-one name="SubsequentVersion" class="DomainObject">
<column name="SUBSEQUENT_VERSION_DOMAIN_OBJECT_ID" />
</many-to-one>-->
<one-to-one name="SubsequentVersion" class="DomainObject" property-ref="PreviousVersion" />
</class>
</hibernate-mapping>
The one-to-one mapping will be always loaded eagarly with NHibernate. Not sure if this is a feature or bug, but that is how it works. If you need lazy load, use many-to-one or one-to-many. Not the best answer I know, but if you can add new column...

Named query not known

I have a mapping in NHibernate like this:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping namespace="News.BusinessEntity" assembly="News.BusinessEntity" xmlns="urn:nhibernate-mapping-2.2">
<class name="News" table="News">
<property name="NewsId" type="Int64" column="NewsId" />
<property name="NewsTitle" type="String" column="NewsTitle" />
</class>
<sql-query name="Sp_News">
<return class="News" />
exec Sp_News
</sql-query>
</hibernate-mapping>
When I call session.GetNamedQuery("Sp_News") I get the following error:
Named query not known: Sp_News.
Any help would be much appreciated.
the error was solved just by setting the Build Action property of .hbm.xml file to Embeded Resource
The same error is thrown if the mapping file doesn't end with .hbm.xml.
I have accidentally renamed a mapping file and dropped the .hbm. from the name, putting it back solved this issue for me.

Multi Table mapped on one class in NHibernate

we use an external Database where we cant edit table designs only add own tables to extend the core tables.
So I need map two tables on one class, i try this:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
assembly="DaVinci"
namespace="DaVinci.Domain">
<class name="Vorgang" table="VORGANGSKOPF">
<id name="Id" column="ID">
<generator class="native" />
</id>
<property name="Vorgangsnummer" column="VORGANG" />
...
<join table="OWN_VORGANG_WAEHRUNG" optional="true">
<key column="VOR_ID" property-ref="Vorgangsnummer" />
<property name="WaehrungVK_Internet" column="WAEHRUNG" />
<property name="WaehrungsKursVK_Internet" column="KURS" />
<property name="Preis_Internet" column="BETRAG_EURO" />
<property name="PreisFremdWaehrung_Internet" column="BETRAG_FREMD" />
</join>
...
After testing i know now that "property-ref" for joins dosn't work.
Bugreport here
Does anyone know an other way to map two tables on one class?
(I'm struggling a little with the table and column names here.)
Could you use a joined subclass for this? Even if the tables don't follow the logical relationship, if there's a 1-to-1 database relationship between the two tables, then you'd get what you want by ignoring the parent, and doing all your operations on the subclass.

NHibernate Subclass of a Joined-Subclass problem

I have an application that has a core assembly with base classes that I need to inherit from.. I need to save these to the database and after reading about NHibernate decided to use it.
However I have a problem with one of my new inherited classes.. I have setup the subclass map but when I save, it neither attempts to save any of it's base class properties or any of it's new ones that I have assigned in the mapping!
My classes are laid out like the following: (from a small demo app)
core assemblies
DataItem -> User
Anything that will touch the database inherits the DataItem class as it handles the id, modified date etc etc..
In my test I setup user to only have a FirstName..
If I save a new User it works great.. however when I inherit from user and then add another property called LastName and attempt to save this new object.. it only puts a sql statement together of INSERT INTO t_User (id) VALUES(?).. it doesn't attempt to save the first name or last name.. either though both have been set and are mapped.
My nhibernate.config:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
<session-factory name="DAL">
<property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
<property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
<property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
<property name="adonet.batch_size">16</property>
<property name="current_session_context_class">web</property>
<property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
<mapping assembly="DAL"/>
<mapping assembly="NHibernateDemo"/>
</session-factory>
</hibernate-configuration>
As you can see I have 2 assemblies.. my DAL is my core and the NHibernateDemo is a web application that uses the core for inheritance.
My core DataItem mapping:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="DAL" namespace="DAL.Model">
<class name="DataItem" table="t_DataItem" >
<id name="Id">
<generator class="native" />
</id>
<discriminator column="typeid" type="System.Int32"></discriminator>
<property name="IsActive" column="isActive" not-null="true" />
<property name="TypeId" column="typeId" not-null="true"></property>
<many-to-one name="Parent" column="ParentId" class="DataItem"></many-to-one>
<bag name="Children" cascade="all-delete-orphan">
<key column="ParentId"></key>
<one-to-many class="DataItem"/>
</bag>
<joined-subclass name="User" table="t_Users">
<key column="id"></key>
<property name="FirstName" column="firstName" not-null="true" ></property>
</joined-subclass>
<joined-subclass name="Email" table="t_Emails">
<key column="emailid"></key>
<property name="Address" column="Address"></property>
</joined-subclass>
</class>
</hibernate-mapping>
My inherited NewUser mapping that doesn't work!:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernateDemo" namespace="NHibernateDemo.Model">
<subclass name="NewUser" extends="DAL.Model.User, DAL" discriminator-value="1">
<property name="LastName" column="LastName"></property>
</subclass>
Why is it that when I attempt to save my class NewUser that it doesn't attempt to save any of the other properties set, whether from it's base or newly declared properties?
I'd really appreciate any help or insight to this.. I must be missing something really simple and I just can't see it.
Thanks,
Mike
It could be that you're not able to mix subclass and joined-subclass mappings in the same class hierarchy. Since your DataItem and User are related by joined-subclass, you may need to make your NewUser class another joined-subclass of User.
Another issue might be the use of the "discriminator" in your current NewUser mapping. The discriminator should be an additional column in your User table that NHibernate uses to tell the difference between a User record and a NewUser record. I'm not sure if this works where the User base class might not specify its discriminator value, whereas the NewUser does. I'm not sure if you're specifying the discriminator-column anywhere, which might also be a problem.
I would suggest first trying to make NewUser a joined-subclass of User.

NHibernate Joined Subclass in Separate Assemblies

I have the following solution project structure:
Application.Core.Entities
Application.Xtend.CustomerName.Entities
In the Core project I have an entity Customer defiend. In the XTend project, I have an entity defined that subclasses Customer named xCustomer (for lack of a better name at this time...).
The idea here is that we have a Core domain model in our application. A customer can then create a new assembly that contains extensions to our core model. When the extension assembly is present a smart IRepository class will return a subclass of the core class instead.
I am attempting to map this relationship in NHibernate. Using Fluent NHibernate I was able to generate this mapping:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
default-lazy="false"
assembly="NHibernate.Core.Entites"
namespace="NHibernate.Entites"
default-access="field.camelcase-underscore">
<!-- Customer is located in assembly Application.Core.Entities -->
<class name="Customer" table="Customers" xmlns="urn:nhibernate-mapping-2.2">
<id name="Id" column="Id" type="Int64">
<generator class="native" />
</id>
<component name="Name" insert="true" update="true">
<property name="LastName" column="LastName" length="255" type="String" not-null="true">
<column name="LastName" />
</property>
<property name="FirstName" column="FirstName" length="255" type="String" not-null="true">
<column name="FirstName" />
</property>
</component>
<!-- xCustomer is located in assembly Application.XTend.CustomerName.Entities -->
<joined-subclass name="xCustomer" table="xCustomer">
<key column="CustomerId" />
<property name="CustomerType" column="CustomerType" length="255" type="String" not-null="true">
<column name="CustomerType" />
</property>
</joined-subclass>
</class>
</hibernate-mapping>
But NHib throws the following error:
NHibernate.MappingException:
persistent class
Application.Entites.xCustomer,
Application.Core.Entites not found
---> System.TypeLoadException: Could not load type
'Application.Entites.xCustomer' from
assembly 'Application.Core.Entites,
Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null'..
Which makes sense xCustomer is not defined in the Core library.
Is it possible to span different assemblies like this? Am I approaching the problem wrong?
I asked this same question on the NHibernate Users mailing list and the solution was so obvious that I am somewhat embarrassed that I couldn't see it.
The hibernate-mapping attributes assembly and namespace are convenient short cuts that allow you to not have to fully qualify your class names. This lets you have the nice mark up , but the name attribute of both class and joined-subclass elements can take a fully qualified assembly name as well.
So the above broken mapping file can be fixed like so:
<joined-subclass name="Application.XTend.CustomerName.Entities.xCustomer,
Application.XTend.CustomerName.Entities, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null"
table="xCustomer">
<key column="CustomerId" />
<property name="CustomerType" column="CustomerType" length="255"
type="String" not-null="true">
<column name="CustomerType" />
</property>
</joined-subclass>
This works as I expected it to. So I then took a look at the Fluent-NHibernate source and created a patch complete with working unit tests to resolve the issue and submitted it to the project.
Thanks for you help #David Kemp
You need to map using the extends attribute of the <class> element (AFAIK, this is new in NHibernate 2.0). Then you can have your subclass mapping (.hbm.xml) in the XTend assembly.
You might have to use the AddAttribute/AddProperty (can't remember what it's called) to do this using Fluent NHibernate. (Or submit a patch).