tags:

views:

294

answers:

6

One thing that bothers me about nHibernate is that it is not 100% compile time tested.

If I rename a column in my database table, and I update the mapping file for that table, when I hit compile I should get errors in all my query code (hql/criteria whatever) of where I referenced that column name and how it is spelled wrong.

The whole point (for me anyway) of using an ORM was that database changes won't break my queries.

In other words, I will be notified at compile time of what needs to be fixed, instead of getting runtime errors etc.

A: 

Hibernate uses dynamic byte code generation to create the mapping classes, based on the mapping configurations.

The fundamental point of ORM is to enable auto-magical mapping (bridge) between Objects and Relational systems. Thus: ORM.

But it is only 1/2 magical to me if it can't tell me when my queries (1000's of them) are not mapping to the correct columns due to column renaming or resizing etc.
Blankman
nHibernate does not design databases for you. It lets you map to them. The design is on your part. We keep scripts in source control for schema changes. Then we know what mappings have changed. If you do not control your schema, nHibernate will not do it for you either.
Devtron
I'm not referring to schema changes, but compile tested queries. At compile time, I want errors telling me that the column doesn't exist that I referenced in my queries.
Blankman
if you are changing columns (aka changing your SCHEMA), nHibernate will not auto-update those mappings. Look at ActiveRecord, as we used this to solve that problem. If you're using pure nHibernate, it will not write queries for you, nor will it auto-update your database changes. You already mapped them once yourself, so you already know that you MUST map them explicitly.
Devtron
I don't want it to auto-update, just tell me when I compile that the column doesn't exist (since it was renamed), I will then go and manually change them.
Blankman
NHibernate uses reflection not byte code compilatio. Tools like postsharp use byte code generation or injection
Chris S
A: 

if you want to strongly type your objects rather than using xml config which can cause alot of runtime issues if not properly tested, I would look into FluentNHibernate which has convention maps that allow you to map your classes to data in code. Made my life alot easier especially when first starting with NHibernate wish i had found it before i knew how to properly map using xml

Brandon Grossutti
A: 

You should look at Castle ActiveRecord. I used this before and it allows you to not worry about the mapping files (.hml) as much. It lets you make your changes at the class level definitions, and the mappings files were generally untouched.

If you are writing bad queries, that sounds like a design problem, not an nHibernate problem.

Devtron
Not sure if you understand me, they are not bad queries, they just don't work because I renamed a column username to say firstname. Now my queries have to be updated, I just want a compile time check of that.
Blankman
+3  A: 

To achieve what you want I think your best solution is to use a combination of Fluent NHibernate and nhlambdaextensions. Fluent NHibernate will give you type-safe checking on your mapping files (so if you change a property on your entity, the compiler will throw an error if you don't also change the property on your mapping class). The lambda function extensions will give you type-safe queries via the Criteria API (not HQL since that's just magic-strings SQL-with-objects).

Also to clarify your question, you said:

If I change a column (rename) in my database table, and I update the mapping file for that table, when I hit compile I should get errors in all my query code (hql/criteria whatever) of where I referenced that column name and how it is spelled wrong.

Just changing the database side should break nothing (assuming you also make the change in your XML mapping file). Your code does not reference the column="first_name" portion of the mapping, it references the name="FirstName" portion. If you do not change your entity, renaming a column (from "firstname" to "first_name", for example) in the database will not break your queries as long as you update your mapping file as well.

Stuart Childs
ahhh, ok so then it looks like its a moot issue then. Thanks for pointing that out!
Blankman
But I guess with criteria query it will break. like when you do SetBlah("asdf")
Blankman
Assuming we're still talking about a DB-only change, no it should not break Criteria. If you have an entity class with a property called LastName, your Criteria query references "LastName" (e.g. `.Add(Restrictions.Eq("LastName", "Example last name"))` ). So as long as you keep the mapping file up-to-date, it doesn't matter if you change the column name to last_name, or lastname, or surname, etc. Your code *always* references your code, if that makes sense. NH separates the concerns of your code and your database.
Stuart Childs
+1  A: 

You won't get errors providing the Property names haven't changed, as most people use HQL for their queries in NHibernate.However if you do change the Property names and not the HQL you will indeed get broken queries, e.g.:

FROM User Where User.Surname = 'bob'

Change the Surname property to Lastname and it'll break. It's a feature lacking in NHibernate but would make a good project for the contrib - a Subsonic style query interface. This a project sort of similar but still use HQL.

As mentioned above ActiveRecord and Fluent NHibernate are the closest to type checking with NHibernate. Both enforce that you inherit your classes from their base class, as you'd expect and ActiveRecord is not intended for production use - Ayende has said in a video that's meant to be a prototyping tool for NHibernate.

Chris S
A: 

Does NHibernate have the equivalent of the Java version's schema validator? In which case, you could add a step to your build process to build the session factory and run the validator-- building the session factory should also compile named queries, hence validating them too.

Hmm, looks like it supports something like that: http://nhforge.org/blogs/nhibernate/archive/2008/11/22/nhibernate-schemavalidator.aspx

NB this means your build process will fail to work if your dev database is not available--- which I would regard as a bad thing.

araqnid