Nhibernate Identity Skips a thousand - nhibernate

i have an application and the main object have an identity like always. in the database the ids are saved in order increased by 1 as expected 1,2,3,4,5,6 .... N... as expected
but when showed in the view the ids are different like 1 to 12 and then they jump a thousand to 1012
the weirdes is that when i debugg it and i do the Session.Query().ToList();
the ids's are bad, and they just came from the database, i haven't map them or anything.
and if i query by id the object is retrieved it correctly.
public class BaseModel {public virtual int Id { get: set; }}
public class WorkOrder: BaseModel {}
and my Mapping
<?xml version="1.0" encoding="utf-8" ?>
<id name="Id">
<generator class="identity" />
</id>
the app is in production, and we have been creating/updating/deleting several work orders many times, and i had this problems before while developing, but it came back.
is it because the ids is inherited by a base model, or is it any kind of bug of Nhibernate?

The identity generator means that the database will generate the ids. I suggest take a look at the column definition there.

Related

Querying by property of mapped subclass in NHibernate

I'm very new to NHibernate so this may be fairly trivial, but searching is leaving me confused.
I have an AddOnAmount table as follows:
AddOnID | AddOnTypeID | Period | Amount
where AddOnTypeID is a FK. The rows have a unique constraint on AddOnTypeID and Period.
The mapping looks like this:
<id name="Id" column="AddOnId" type="long">
<generator class="native" />
</id>
<many-to-one name="AddOnType" column="AddOnTypeID" class="AddOnTypeStatic" not-null="true" />
<property name="Period" />
etc.
The AddOnTypeStatic class/table just has an Id, which is the numerical value stored on the table, and a descriptive Name.
I'm trying to write a query that will search by AddOnTypeId and Period, so I can validate the existence (or not) of a row before attempting to add a duplicate from my front end, but I'm not sure how to do that as the AddOnAmountStatic class has a subclass whereas the table has just an Id.
So far I've written:
public AddOnAmountStatic FindByAddOnTypeAndPeriod(long addOnType, string period)
{
return FindOne(CreateCriteria()
.Add(Restrictions.Eq("AddOnTypeId", addOnType))
.Add(Restrictions.Eq("Period", period))
.SetCacheable(true));
}
which does not work, as AddOnTypeId isn't a property of AddOnAmountStatic. Not sure how to access the property of the subclass in this context.
My mapping works, as I've been using it so far with no problems.
Solved my problem - it was simple but thought I'd add the solution here in case it helps anyone else.
I'd been thinking of constructing the query from the table's perspective (i.e., with the AddOnTypeID), whereas what I should have done is look at it from the entity's perspective. In other words, I just needed to pass in an AddOnTypeStatic object.
What I did was take my AddOnTypeID parameter, check it exists through NHibernate (returning either an AddOnTypeStatic object or null) then passed that through to the original query. Final query is simply
return FindOne(CreateCriteria()
.Add(Restrictions.Eq("AddOnType", addOnType))
.(Restrictions.Eq("Period", period))
.SetCacheable(true));
Hope this helps another newbie!

NHibernate persist object changes for approval

I am building an application that allows users to make changes to objects, but the changes have to be approved before they are made permanent. I am using NHibernate.
How would you handle this sort of scenario using? Are there any articles out there that tackle this issue?
I am thinking of having two tables for each object. One for the current state and one for the proposed state. Then having a Generic ChangeRequest object that would specify the Delete/Insert/Update and the subject that wants to be changed. But, I don't believe NHibernate will allow you to have two different mappings for the same object.
The two options off the top of my head...
Each object could have an approved flag or approved date. (This could be encapsulated in a common base class.) You would either need a composite key including the approval column (not recommended - composite keys are a pain) or each object could have a business key in addition to the PK. This would mean one table per entity with some extra metadata columns in each table to determine approved. (You could decide whether to keep all changes or only the latest.)
The other option would be two separate tables for each object. You can do this using Entity Names, which were introduced in NH2.1. Easiest to show an example. We have only one class definition:
public class Foo {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
We have two hbm.xml files. Note the entity-name attribute after the class. This creates two tables, Foo1 and Foo2. (You could pick your own names via the table attribute.)
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="NhHacking" assembly="NhHacking">
<class name="Foo" entity-name="Foo1">
<id name="Id">
<generator class="native" />
</id>
<property name="Name"/>
</class>
</hibernate-mapping>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="NhHacking" assembly="NhHacking">
<class name="Foo" entity-name="Foo2">
<id name="Id">
<generator class="native" />
</id>
<property name="Name"/>
</class>
</hibernate-mapping>
When we save the entities, we provide the entity-name with the operation:
var foo1 = new Foo {Name = "Foo1"};
var foo2 = new Foo {Name = "Foo2"};
session.Save("Foo1", foo1);
session.Save("Foo2", foo2);
This allows you to select which table the entity goes to. You would of course want to encapsulate the entity names in a constants class. You need to specify the entity name for all operations (session.Get(), session.Save(), session.Update(), session.Delete(), etc.)
For your case I would suggest that each object will have the following design: PropertyName, PropertyValue, PropertyStatus (propesed/approved). By this desing you can alter your objects in any way while keeping one mapping for the file.
For example if a person table should have the columns ssn, name, birthdate .... In this desing you will have 3 rows:
In regular design
-----------------
ColumnName ColumnValue
ID 1
ssn 123
name xyz
birthdate dd/mm/yyy
This will be
------------
PropertyName PropertyValue ObjectID PropertyStatus
ssn 123 1 approved
name xyz 1 approved
birthdate dd/mm/yyyy 1 approved
Think of it as if it is a vertical table where rows are column and vice versa.

Strategies for Mapping Views in NHibernate

It seems that NHibernate needs to have an id tag specified as part of the mapping. This presents a problem for views as most of the time (in my experience) a view will not have an Id. I have mapped views before in nhibernate, but they way I did it seemed to be be messy to me.
Here is a contrived example of how I am doing it currently.
Mapping
<class name="ProductView" table="viewProduct" mutable="false" >
<id name="Id" type="Guid" >
<generator class="guid.comb" />
</id>
<property name="Name" />
<!-- more properties -->
</class>
View SQL
Select NewID() as Id, ProductName as Name, --More columns
From Product
Class
public class ProductView
{
public virtual Id {get; set;}
public virtual Name {get; set;}
}
I don't need an Id for the product or in the case of some views I may not have an id for the view, depending on if I have control over the View
Is there a better way of mapping views to objects in nhibernate?
Edit
Answer So Far
Mapping
<class name="ProductView" table="viewProduct" mutable="false" >
<id name="Id" type="Guid" />
<property name="Name" />
<!-- more properties -->
</class>
Class
public class ProductView
{
public virtual Name {get; set;}
//more properties
}
View SQL
Do I still need NewID()?
Select NewID() as Id, ProductName as Name, --More columns
From Product
You can make it just a little bit cleaner by not mapping the Id to a property and omitting the generator:
<id column="Id" type="guid"/>
That way, you keep the problem in the data layer, without leaking the implementation detail to your domain.
As far as I know, NHibernate will require either an id or a composite-id definition since it's the mechanism by which it uniquely identifies a given record. If there is no combination of columns that provides a key for each row in the view, I think you are stuck with hacky workarounds.

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.

Why is NHibernate deleting immutable class instance?

I'm trying to migrate an app from NHibernate 1.x to 2.1, and I've noticed something odd: my immutable objects are being deleted in my integration tests.
For example, this test used to pass:
[Test, ExpectedException(typeof(NHibernate.HibernateException))]
public void DeleteExistingInstanceThrows()
{
// Note: NHib transaction is opened/rolled back in test setup/teardown
m_testRecordId = CreateRecordInDB();
var dao = new NHibFactory().GetTransDao();
var obj = dao.GetById((long)m_testRecordId, false);
dao.Delete(obj);
dao.CommitChanges();
Assert.IsFalse(TestRecordExists(m_testRecordId));
}
The call to CommitChanges should throw, because of trying to delete an instance whose type is mapped with mutable="false". However, after updating the expected exception type, this test now fails (because no exception is thrown). I've checked the database and traced through the test, and the record is created, the instance is loaded, and the record gets deleted again afterwards.
The class in question is mapped to the same table as another class - it is more-or-less intended as a read-only view of a subset of that data. Here's the class mapping:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class name="Sample.Trans, Sample" table="tblTrans" mutable="false">
<id name="Id" column="transId" unsaved-value="0">
<generator class="identity" />
</id>
<property name="Amount" column="amount" type="Decimal" />
<!-- ...a half dozen other mapped fields... -->
</class>
</hibernate-mapping>
I expect I'm missing something basic, but I've been scouring the web for any reason why the mutable attribute might be ignored, and I've come up empty.
UPDATE:
Logging with Log4Net, it's clear that NHibernate was sending the delete command to the database.
After having dug into it, I found this block of code commented out in the DefaultDeleteEventListener's OnDelete method:
/*
if ( !persister.isMutable() ) {
throw new HibernateException(
"attempted to delete an object of immutable class: " +
MessageHelper.infoString(persister)
);
}*/
As a result, no exception is raised when attempting to delete an immutable instance, and the deletion does actually occur afterwards as if the instance were mutable.
I've sent a note to an NHibernate maintainer with my findings - looks like a bug to me.
Noted by another poster, this issue was fixed in release 2.1.1 from Oct 31 2009.
UPDATE:
As of February 2011, NHibernate is now able to delete immutable class instances again. Immutable objects should be deletable - the fact that they were originally not was the actual bug.
I had exactly the same problem in the same situation (upgrading from 1.x). The bug was fixed in 2.1.1 which was released Oct 31.
/Emil