NHibernate generator for a property value (either from a sequence or autoincrement) - nhibernate

I have the following nHibernate Mapping and a corresponding class. The mapping works fine.
I want the value of the field 'RfpId' to be auto inserted starting from '1'.
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping namespace="IBeam.Core.Models" assembly="IBeam.Core" xmlns="urn:nhibernate-mapping-2.2">
<class name="Rfp" table="EST_MRFP" schema="test$tran">
<id name="Id" type="long">
<generator class="sequence" >
<param name="sequence">test$masters.global_sequence</param>
</generator>
</id>
<property name="RfpId" column="RfpId" type="String" not-null="true" />
<property name="Title" column="Title" type="String" not-null="true" />
</class>
</hibernate-mapping>
How can I do this? Right now I have created an oracle sequence 'RfpSequence'. And before every new record of type Rfp is inserted, I fetch the NEXTVAL from RfpSequence by running a query. Is there any way where nHibernate can do this for me, just like it does for the Id field.

Is the database responsible for the increment? If so try:-
<property name="RfpId" generated="always" update="false" insert="false" />
There is caveat as NH will need to perform a select straight after the insert to update the value.

Related

Nhibernate: one-to-one to one-to-one

I have the following UML structure:
I'm trying to map it similar to this:
<class name="Parent" table="ParentTable">
<id name="Id">
<generator class="guid.comb" />
</id>
<one-to-one name="Child" class="IChild" property-ref="Parent" cascade="all" />
</class>
<class name="IChild" table="ChildTable" abstract="true">
<id name="Id">
<generator class="foreign">
<param name="property">Parent</param>
</generator>
</id>
<discriminator column="TypeKey" type="String"/>
<one-to-one name="Parent" class="Parent" />
<one-to-one name="Child" class="IGrandchild" property-ref="Parent" cascade="all" />
</class>
<subclass name="ConcreteChild" extends="IChild" discriminator-value="ConcreteChild1">
<property name="SomeProperty"/>
</subclass>
<class name="IGrandchild" table="GrandchildTable" abstract="true">
<id name="Id">
<generator class="guid.comb" />
</id>
<discriminator column="TypeKey" type="String"/>
<many-to-one name="Parent" class="IChild" unique="true" column="ChildTableFk" />
</class>
<subclass name="ConcreteGrandchild" extends="IGrandchild" discriminator-value="ConcreteGrandchild1">
<property name="SomeOtherProperty"/>
</subclass>
Working against SQL this doesn't work (strangely, with SQLite this does work). NHibernate first inserts the Parent with the generated guid. It then inserts the child with the same guid. But when it comes to inserting the grandchild, it inserts it with ChildTableFk null (and never attempts to update the FK value).
Additional points:
I prefer not changing the IChild mapping to use many-to-one with FK if possible (I prefer a shared PK).
I can't change the IGrandChild mapping to use a foreign generator because the grandchild can be changed after the object graph is changed, which NHibernate does not support with a foreign generator (an IChild instance, on the other hand, will never change for the lifecycle of a given IParent).
Other than that, any suggestions are welcome, including alternate mapping styles (as long as they support polymorphic IChild and IGrandchild objects).
Oops, seems that I just forgot to set the Parent property on the Grandchild. Should have been the first thing I looked at.

NHibernate: Query by discriminator on association

My question is similar to this question.
But I want to query by the discriminator of a child entity associated with a one-to-one relationship, and without knowing the exact discriminator value, i.e., by type not by string.
Given an hbm like:
<class name="Parent" table="ParentTable">
<id name="Id">
<generator class="guid.comb" />
</id>
<one-to-one name="Child" class="IChild" property-ref="Parent" cascade="all" />
</class>
<class name="IChild" table="ChildTable" abstract="true">
<id name="Id">
<generator class="foreign">
<param name="property">Parent</param>
</generator>
</id>
<discriminator column="TypeKey" type="String"/>
<one-to-one name="Parent" class="Parent" />
</class>
<subclass name="ConcreteChild" extends="IChild" discriminator-value="Concrete1">
<property name="SomeProperty"/>
</subclass>
Or any other one-to-one configuration, I would like to run a query similar to this:
public IEnumerable<Parent> FindByChild(Type childType)
{
return session.CreateCriteria<Parent>()
.Add(Restrictions.Eq("Child.class", childType))
.List<Parent>();
}
Further information:
The above criteria query fails because "Child.class" is not recognized as valid.
A similar query using HQL fails because NHibernate uses the fullname of childType rather than its discriminator value in the query.
Have you tried using an alias? I can't test it right now on my machine, but should be similar to this..
return session.CreateCriteria<Parent>()
.CreateAlias("ParentChild","Child")
.Add(Restrictions.Eq("ParentChild.class", childType))
.List<Parent>();
where ParentChild is just the name I used to refer to the Child entity of the Parent class

nHibernate deleting and re-inserting many to many values when flushing the session

Consider the Following table mapping, this is not more than classic User security role mapping example.
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Model.User, Domain" table="[User]">
<id name="UserID" column="UserId" type="Int32">
<generator class="hilo">
<param name="table">NhibernateUniqueKey</param>
<param name="column">NextHi</param>
<param name="where">TableName='[User]'</param>
<param name="max_lo">20</param>
</generator>
</id>
<property name="UserName" column="UserName" type="String" length="20"/>
<property name="Password" column="Password" type="String" length="20"/>
.
.
<bag name="SecurityRoles" table="UserSecurityRole" lazy="false">
<key column="UserId"></key>
<many-to-many class="Model.SecurityRole, Domain" column="SecurityRoleId"></many-to-many>
</bag>
The problem is when i retrive the user by username [using a criteria query], and flush the session all the security roles attached to the retrieved user gets deleted and re-inserted again, although i do not make any modifications to the retrived object.
Am i doing something wrong here or is this the way nhibernate works by design ?
That's the behavior of bag. To avoid it, use idbag or set.

Can I "join" two tables into one class whilst also creating many-to-one relationships using NHibernate?

We have a legacy database schema which I've tried (unsuccessfully) to map with NHibernate. To give a simplified example, say I want a Person class whose first name comes from the "Person" table, but their last name comes from the "Person2" table. The "Person" table also has the Id of the person's Car and I want my Person class to have a Car property. I can map all that using the following;
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="NHibernateMappingTest.Person, NHibernateMappingTest" lazy="false">
<id name="Id" >
<generator class="native" />
</id>
<property name="FirstName" />
<many-to-one name="Car" access="property" class="NHibernateMappingTest.Car, NHibernateMappingTest" column="CarId" cascade="save-update"/>
<join table="Person2">
<key column="PersonId" />
<property name="LastName" />
</join>
</class>
</hibernate-mapping>
The lets me combine the Person and Person2 tables, and the lets me find their Car - everything works fine.
But... if the Person2 table happens to have the person's HouseId, I'd like to be able to add a second element to my mapping...
<many-to-one name="House" access="property" class="NHibernateMappingTest.House, NHibernateMappingTest" column="HouseId" cascade="save-update"/>
...so that my Person class can have a House property.
However this is where it all goes wrong, because the SQL which NHibernate generates assumes that the HouseId column is in the Person table (but it's not, it's in Person2), so I get the following error;
MySql.Data.MySqlClient.MySqlException: #42S22Unknown column 'HouseId' in 'field list'
Is NHibernate able to do what I'm attempting, is there a different way to achieve this (without changing the database schema), or have I just made a beginner's error in my map file?
Vincent - thanks for your response. No I wasn't nesting the tag element inside the element. But following your suggestion, I tried and it works perfectly! Thanks very much for responding.
<hibernate-mapping default-cascade="save-update" xmlns="urn:nhibernate-mapping-2.2" auto-import="true">
<class name="NHibernateMappingTest.Person, NHibernateMappingTest" lazy="false">
<id name="Id" >
<generator class="native" />
</id>
<property name="FirstName" />
<many-to-one name="Car" access="property" class="NHibernateMappingTest.Car, NHibernateMappingTest" column="CarId" cascade="save-update"/>
<join table="Person2">
<key column="PersonId" />
<property name="LastName" />
<many-to-one name="House" access="property" class="NHibernateMappingTest.House, NHibernateMappingTest" column="HouseId" cascade="save-update"/>
</join>
</class>
</hibernate-mapping>

NHibernate SchemaExport with generated properties

I'm wondering if there is a way to get SchemaExport to generate and identity column for a generated property.
<id name="Id" column="Id" type="Guid">
<generator class="guid.comb" />
</id>
<property name="OrderNumber" column="OrderNumber" type="Int32" generated="insert"/>
With the mapping above, ShcemaExport does not make the OrderNumber column an Identity column.
Greg
I figured it out, with Fabio Maulo's help:
<property name="OrderNumber" generated="insert" update="false">
<column name ="OrderNumber" sql-type="int identity" not-null="true"/>
</property>