property formula not returning the result - nhibernate

I have a table Submission, which has a many to one mapping to a SubmissionType, which has a one to many mapping to SubmissionTypeYear table. Even though this is a one-to-many mapping, there will always be just one SubmissionTypeYear for a SubmissionType. (Don't ask me why the database was designed like this. I wasn't involved and I just have to make it work.)
Therefore, a submission will have a SubmissionType will have a SubmissionTypeYear.
My problem is that in my Submission.hbm.xml, I want a calculated property, which gets me a column value from SubmissionTypeYear. But I don't know what's wrong, it comes back with a zero, when I know that there is a value in the table.
This is my code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="Business.Domain" assembly="Business.Domain">
<class name="Business.Domain.Submission, Business.Domain" table="dbo.Submission" lazy="true" optimistic-lock="version" >
<id name="Id" column="SubmissionId">
<generator class="identity"/>
</id>
<discriminator column ="SubmissionTypeCode"></discriminator>
<many-to-one name="SubmissionTypeMember" insert="false" column="SubmissionTypeCode" class="RefSubmissionType" access ="field.camelcase-underscore" cascade ="none" />
<property name="Year" formula="(SELECT TOP 1 SubmissionTypeYear.Year FROM SubmissionTypeYear WHERE SubmissionTypeYear.SubmissionTypeCode = SubmissionTypeCode)" access="field.camelcase-underscore"></property>
</hibernate-mapping>
I thought that it wasn't picking up the SubmissionTypeCode correctly, so I tried with a static string as well, but doesn't seem to be working.
What am I doing wrong? Please help.
Thanks

OK, I figured it out. The problem was with the new Submission types created. As it was a new object and not yet stored in the database, it wasn't able to pick up the calculated field. It was working for all the existing objects. Fixed :)
Hope this helps someone else.

Related

NHibernate and Integer Columns as Version

I'm trying to create a DB Table, using an NHibernate *hbm.xml mapping file, that will have a Versioning Column for concurrency check. The Versioning column should be a nullable Integer.
Although the Database is created just fine, using the mapping file as reference, the following happen:
* The first record is inserted with a NULL value as the Version
* The update of the previously inserted records fails with a "Stale Data" exception
In other words, no matter what I do, the Version column is always NULL.
I'm somewhat new to the Concurrency Control using NHibernate, so I don't quite understand what I'm doing wrong..
If I use a Timestamp as a Version, everything works just fine. However, my requirement is to use an Integer.. Hence my problem.
This is my Mapping File:
<?xml version="1.0" encoding="utf-8"?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-lazy="true" auto-import="false" assembly="New1.Backend" namespace="New1.BO">
<class name="Natrio" table="`Natrios`" schema="`dbo`">
<cache usage="read-write" />
<id name="Id" column="`Id`" type="System.Int32">
<generator class="NHibernate.Id.Enhanced.TableGenerator">
<param name="increment_size">200</param>
<param name="segment_value">Natrios</param>
<param name="optimizer">pooled-lo</param>
</generator>
</id>
<version name="Version" column="`Version`" type="System.Nullable`1[[System.Int32, mscorlib]], mscorlib" generated="always" unsaved-value="0">
<column name="`Version`" not-null="false" sql-type="int" />
</version>
<property name="Attribute" column="`Attribute`" type="String" not-null="false" length="100" />
</class>
</hibernate-mapping>
Any thoughts and/or suggestions would be greatly appreciated!
Why do you need nullable version column? In any case I believe the issue is caused by unsaved-value="0" in your mapping. As default value for nullable column is null - NHibernate thinks that value is already generated and so it's never assigned. You need to set it to null - unsaved-value="null" to make it work with nullable columns. And unsaved-value="0" makes sense for not-nullable types. But better omit this attribute completely and let NHibernate to s
Another issue with generated attribute. It's about DB generation - so always means that this value is generated automatically by DB. You should remove it or specify it as generated="never".
I believe the following mapping should work for you:
<version name="Version">
<column name="`Version`" not-null="false" sql-type="int" />
</version>

Using nHibernate secondary cache for a many-to-one reference

I'm trying to get nHibernate to use second-level cache with a many-to-one relationship, however I can't find any clear explanation on how to set it up correctly. I found this How to get nhibernate to cache tables referenced via many-to-one - is my config correct?, but the example sJHonny provided is for one-to-many and it's not working for me when I adopt it. There are other posts going over this subject, but none of them are specific enough.
The XML config I provide works (I had to edit dramatically, so "hopefully" works), but lookup objects are being cached only when they are retrieved as DataObject is queried. I'd like to know 1) where/how to preload the LookupObject collection? 2) what if I assign this collection to a region and set expiration, then where/how do I reload the cache again? 3) how to change the DataObject's hbm.xml such that nHibernate doesn't generate a join with the LOOKUP table, i.e. such that lookup objects always come from the secondary cache, only getting the DATA.LOOKUP_ID from the db, not the LOOKUP.NAME?
LookupObject.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="BusinessObjects" assembly="BusinessObjects">
<class name="LookupObject" table="LOOKUP" mutable="false" batch-size="20">
<cache usage="read-only" />
<id name="Id" column="ID" />
<property name="Name" column="NAME" />
</class>
</hibernate-mapping>
DataObject.hbm.xml
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="BusinessObjects" assembly="BusinessObjects">
<class name="DataObject"
table="DATA" mutable="false">
<composite-id>
<key-property name="Id" column="ID"/>
<key-property name="Date" column="DATE" type="Date"/>
</composite-id>
<many-to-one name="LookupObject" not-null="true" column="LOOKUP_ID" fetch="join">
</class>
</hibernate-mapping>
I believe I answered my own questions. 1) For preloading the entire collection, I just needed to change my code such that the entire list of lookups is always pulled from the DB and cached, then I get the individual object by ID with LINQ. 2) Same as before. 3) I haven't tested this yet, but I need to remove fetch="join" from many-to-one element because otherwise the SQL join will still be generated and data will be still returned. Then set the lookup object without nHibernate by getting it from cache.

NHibernate simple collection of joined-subclass entities

I'm trying to map a set of joined-subclass entities to a parent entity. The SQL being produced by NHibernate seems to be incorrect. Am I missing anything in my mapping? Is there another way I can approach this problem?
<class name="ResultItem" table="result">
<id name="ID">
<generator class="identity" />
</id>
<many-to-one name="Job" column="JobID"/>
<property name="Timestamp"/>
<many-to-one name="User" column="UserID"/>
<joined-subclass name="ResultItemAttachment" table="result_attachment">
<key column="ID"/>
<property name="Comment"/>
</joined-subclass>
</class>
This is the SQL being generated by NHibernate. It seems as if its getting confused between super and sub class members? The only table with JobID is the result table and not result_attachment.
SELECT attachment0_.JobID as JobID1_,
attachment0_.ID as ID1_,
attachment0_.ID as ID26_0_,
attachment0_1_.JobID as JobID26_0_,
attachment0_1_.`Timestamp` as Timestamp26_0_,
attachment0_1_.UserID as UserID26_0_,
attachment0_.`Comment` as Comment33_0_
FROM result_attachment attachment0_
inner join result attachment0_1_ on attachment0_.ID=attachment0_1_.ID
WHERE attachment0_1_.JobID=?;
Thanks in advance
I'm afraid this is currently a bug in NHibernate (in there since 2.1 :|) apperently there is a fix in the current alpha of 3.2
https://nhibernate.jira.com/browse/NH-1747
Possible work around is to manually fetch the bag at runtime. Hardly ideal, other option would be to try and get the alpha version running but running an alpha in a production environment is hardly a great idea.

How to avoid a join using NHibernate 2.1 per table inheritance

I'm doing some per table inheritance and all is working great- but I'm noticing that when I want the base entity (base table data) NHProf is showing a left outter join on the child entity / (related table)
How can I set the default behavior to only query the needed data - for example: When I want a list of parent elements (and only that data) the query only returns me that element.
right now my mapping is similar to the below:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="FormBase, ClassLibrary1" table="tbl_FormBase">
<id name="BaseID" column="ID" type="Int32" unsaved-value="0">
<generator class="native" />
</id>
<property name="ImportDate" column="ImportDate" type="datetime" not-null="false" />
<joined-subclass table="tbl_Form" name="Form, ClassLibrary1">
<key column="ID"/>
<property name="gendate" column="gendate" type="string" not-null="false" />
</joined-subclass>
</class>
</hibernate-mapping>
And the example where I want all the data back vs ONLY the parent entity is shown below:
Dim r As New FormRepository()
Dim forms As List(Of Form) = r.GetFormCollection().ToList()
Dim fbr As New FormBaseRepository()
Dim fb As List(Of FormBase) = fbr.GetFormBaseCollection().ToList()
You can't. It's called "implicit polymorphism" and it's a rather nice (albeit unwanted in your case :-) ) feature provided by Hibernate. When you query a list of base objects, the actual instances returned are of the actual concrete implementations. Hence the left join is needed for Hibernate to find out whether particular entity is a FormBase or a Form.
Update (too big to fit in comment):
The general issue here is that if you were to trick Hibernate into loading only the base entity you may end up with inconsistent session state. Consider the following:
Form instance (that is persisted to both form_base and form tables) was somehow loaded as FormBase.
You've deleted it.
During flush Hibernate (which thinks we're dealing with FormBase and thus is blissfully unaware that there are 2 tables involved) issues a DELETE FROM form statement which throws an exception as FK is violated.
Implicit polymorphism exists to prevent that from happening - Form is always a Form, never a FormBase. You could, of course, use "table-per-hierarchy" mapping where everything is in the same table and thus no joins are needed but you'll end up with (potentially) a lot of NULL columns and - ergo - inability to specify not-null on children's properties.
All that said, if this is REALLY a huge performance issue for you (which it normally shouldn't be - presumably it's an indexed join), you could try using a native query to just return FormBase instances.

nhibernate many to many association - property returns null set

I have a many to many relationship between A and B. (I know I can consider refactoring etc, but that's another matter).
my Code does something like this:
// given aId is the Id of an instance of A, and A has a many to many set of B's
A a = myActiveSession.Get<A>(aId);
a.Bs.Add(new B() {Name="dave"});
and I get an exception because a.Bs is NULL.
this only happens in the context of a test suite, and when I run the single test I get a set and everything is ok.
I expect that since the default is lazy fetch, Bs will be initialized when I access the property getter, but if this fails I expect to get an exception, and not simply null... since this way I have no immediate clue what caused this. any ideas?
PS: this is the mapping:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
namespace="MyNamespace" assembly="MyAssembly">
<class name="A" table="A" dynamic-update="true">
<id name="id" type="integer" access="field">
<column name="ID"/>
<generator class="native"/>
</id>
<property name="name" type="string" access="field"/>
<set name="Bs" table="A_B">
<key column="a_id"/>
<many-to-many column="b_id" class="B" />
</set>
</class>
</hibernate-mapping>
UPDATE: I've managed to get this to work when I fixed some code that did session cleanup (see #Darin Dimitrov's suggestion), however, I still don't understand what could have caused this strange behavior (instead of receiving some clear exception). so at the moment this remains a mystery.
Unit tests could execute in parallel from different threads and for this reason they should be independent. I suspect that in your case the Session object is reused in multiple tests and one another test could messes up with Bs property. Make sure the session is created inside your test and is destroyed afterwards i.e.
using (var session = sessionFactory.OpenSession())
{
A a = myActiveSession.Get<A>(aId);
}