How could nHibernate not be 100% compile time tested? - nhibernate

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.

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.

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.

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.

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.

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

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://nhibernate.info/blog/2008/11/22/nhibernate-schemavalidator.html
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.

Related

A single place in NHibernate and Sharp Architecture to specify field length for database and validation

I'm building a new system with NHibernate, using S#arp Architecture. I'm new to S#arp, but experienced with NHibernate. One feature I was really hoping to find was a nice way to specify in one place text field lengths that would be carried through to every layer that needs to know the length.
In other words, I use Fluent mapping to specify that the Name field of a Whatsis object is 50 characters. (I turned off automapping because I was still writing mapping overrides for most, if not all classes. I decided just to write the full mapping myself with ClassMap. I want enough detail in the mapping to generate the complete DB schema from it.) Then when I generate the database schema using hbm2ddl, I get a 50-character field length. That's great. But I also want the MVC validators to enforce it automatically. And I'm so greedy I even want the proxy object the NHibernate generates for Whatsis to know about that length in its setter, so if in code I should assign a too-long value, I'll get an exception.
Do I have any hope of achieving this without really overcomplicating my project? This is my first time using Fluent mapping. I thought this was a feature of Fluent, but it looks like it doesn't work that way after all.
You need to use NHibernate Validator as that is the only validator framework that NHibernate hbm2ddl currently supports. Unfortunately it doesn't look like anyone has wired together NHibernate Validator and MVC3 validations. Here is someone else having problems with it:
MVC 3, NHIbernate Validators & Message Interpolator
It should be possible as I've used xVal (predecessor to MVC3 validators) in the past with NHibernate Validator attributes for client-side validation, server-side validation, and schema generation. Someone just needs to invest some TLC to get NHibernate Validator playing nicely with MVC3 validators.

Same business entity for identical tables?

I got a legacy database which have about 10 identical tables (only name differs).
Is it possible to be able to use the same business entity for all tables without having to create several classes/mapping files?
You can use the entity-name feature if you are using NHibernate v2.1 or higher. It is poorly documented but I am actively using the feature. It has gotten hard to find the documentation on it but look here:
Section 5.3 in
http://docs.jboss.org/hibernate/core/3.2/reference/en/html/mapping.html#mapping-entityname
A couple of things to be aware of. You must now use entity-name instead of class name to refer to the objects. In general it is not an entirely transparent change moving from class names to entity names.
Session actions now require two parameters, for example:
_session.Save("MyEntity", myobject)
The entity-name controls what table the data goes into.
Some HQL queries do not work right anymore, sometimes you must use Criteria instead.
If you need a set of sample code I may be able post some, but far too busy at the moment. I suggest you look at the limited info you can find and set it up for a very simple object and multiple tables to learn how it all works. It does work.
You can create a base class with all the properties, but you still need to map them all.
For that, you can either use copy&paste, XML entities (see examle at http://nhibernate.info/doc/nh/en/index.html#inheritance-tableperconcreate-polymorphism), or a code-based mapping method (Fluent or ConfORM). They usually make reuse easier.

Using nHibernate to retrieve Database Schema

Is it possible to generate a schema of a database from nHibernate, where I have provided nHibernate with the configuration to the database but I have not written any mappings.
I wish to get the Database MetaData/Schema programmatically.
I am using an Oracle Database. I have tried two approaches:
Approach one:
public DatabaseMetadata GetMetadata(DbConnection connectionIn)
{
return new DatabaseMetadata(connectionIn, _dialect);
}
Problem: This seems to be what I need however, although it correctly connects, it hasn't picked up any of my tables. All I provided was the nHibernate Configuration object which was populated with the contents of my nHibernate.xml.config file (connection string, driver client, etc).
Question: Why would it not return the table data? It's connected correctly but finds nothing!
Approach two:
public void DatabaseSchema()
{
var schema = new SchemaExport(nHibernateConfiguration);
schema.SetOutputFile("schema.dll");
schema.Create(true, true);
}
nHibernateConfiguration is an instance (property on class) of the nHibernate Configuration object, populated with contents from the nHibernate.xml.config class.
Problem: This simply doesn't work. Crashes with the following exception:
NHibernate.MappingException : Dialect
does not support identity key
generation
I suspect this will only generate a schema based on mappings you have created? I have created no mappings. The idea is this will work against whichever database I have connected to a generate a schema for it.
Question: Is my belief that this method will only generate a Schema based on my mappings? If not, Am I using it correctly?
Hopefully this is clear enough, comment if I need to provide more info.
Thanks In Advance.
To be clear: I have a database and want to get meta data representing the database, a schema.
NHibernate is actually based on the mapping files. You could generate classes or tables from them. There are tools to generate the mapping files, but they are based on the classes, not the tables.
Answers to your specific questions:
Approach one: NHibernate does not read table definitions from the database. All the table definitions need to be specified in the mapping files.
Approach two: SchemaExport creates an SQL file (Create tables, indexes etc) from the mapping definitions. It is actually recommended to use it, unless you need to cope with legacy databases. The output file should be called *.sql, not *.dll.
The error you get is most probably because you try to create an identity id on an oracle database (or another which does not support identity columns). Use hilo instead (or, if you don't like it, guid.comb or native). I just wonder why you get this error, I thought that you didn't write any mapping files?
Conclusion:
I don't know of any tool which create NHibernate mapping files from database tables. There may be one, most probably it is not free or not mature (because otherwise it would be well known). So I suggest to think about generating the table definitions instead, or, in case you have a legacy database, you need to go through writing the mapping files manually.
There are several tools to help you out but the two I use the most are the following two.
NHibernate Schema Tool
NHibernate Mapping Generator
If you already have a schema you can use the NHibernate Mapping Generator to create your mappings. You can then use the mappings for whatever you want. Modify them and use NHibernate Schema Tool to manage the actual schema.
If you don't have any schema and that is what you are trying to create you are on the right track. First you need to "map" your classes. Preferably using Fluent NHibernate or ConfORM like Michael Maddox suggested.
I don't know the purpose of this. If it is database schema management I would recommend against using NHibernate. NHibernate was never developed as a schema manager tool so it probably should not be used this way. Admittedly I might have misunderstood you somehow and this answer could be completely wrong.
I may be interpreting the question wrong, it's not really clear what you are asking for.
Assuming you have created classes and configured NHibernate correctly and you want to create tables in the database for those classes, you have at least two potential ways to try to generate a database without creating NHibernate mappings, both of which will likely work much better with at least some hints about how to do the mappings:
Fluent NHibernate Automapper
ConfORM
There is a decent learning curve for both options.
Another option is to try one of the commercial visual designers for NHibernate, although those tools aren't quite mature enough to do this really well in my experience.
Core NHibernate is not designed or intended to create tables without mappings files.

Linq to Sql compared to NHibernate mapping options

I'm pretty much a newbie and I need to dig into this matter to write some college article so I need some bootstrap.
Here and there I read that NHibernate offers much more flexibility (compared with L2S) in mapping domain model to database. Can you write down some hints what should I explore?
One thing to consider is that L2S "does it for you" by creating the objects in an extremely large DBML file. You can work with your objects by creating partial classes, but if you decide to try to make any changes to the dbml files you are screwed because L2S will either overwrite your changes when it regenerates itself or you will have to implement any changes manually going forward.
So you are kind of stuck because its a terrible idea to change the DBML, but because of that there are limits to what you can do in terms of naming properties of your objects. A classic example is in the case of using enums that get stored as ints in your database. Lets say you have UserType as a enum in your app, in your user table you would probably just store that as an int column named UserType. Thats great except when you create your DBML file you get UserType mapped as an int column... but if you really want the property UserType to return a UserType enum you are forced to either hack the DBML... or change your naming conventions in your database to match your ORM tool... neither of which are good options.
Whereas nHibernate is just an XML based mapping between YOUR objects and YOUR database which gives you significantly more flexibility in terms of how you want to set things up.
another thing to look at is the many-to-many relationships and the table-per-subclass/ table-per-class mappings that are referenced here:
http://nhibernate.info/doc/nh/en/index.html
I don't believe that L2S can handle table-per-subclass relationships.
Hope this helps,
-Max
Specifically you will probably want to look at the limitations that LINQ to SQL has mapping many to many relationships. This is a big difference between in the mapping between the two products.

NHibernate or FluentNHibernate or ActiveRecord?

I am in a stage of mapping my CSharp classes into database tables. I have decided to use NHibernate as my ORM tool after comparing with other tools. I have never done a real project with NHibernate before and now am considering alternatives for the mapping,
ActiveRecord: according to the project's web site, using ActiveRecord can boost productivity dramatically. However, I do not like the idea of adding attributes to my CSharp classes. After all, my class should NOT have any knowledge of database relationships. By using ActiveRecord will bind my nicely separated classes to ActiveRecord, and give me hard time if I ever want to switch underline DAO Layer implementation in the future.
FluentNHibernate: FluentNhibernate was my first attempt when starting mapping. But I also have a few issues with this approach. 1) I don't like my mapping strategies compiled as binary files. I would like to be able to change mapping by modifying xml files. 2) The maturity of FluentNHibernate. NHibernate has been around for a long time, and has LOTS of users, so I am quite comfortable with its maturity. On the contrast, FluentNhibernate is relatively young and not been tested by as many users. Even though I could dive into the source to fix whatever issue comes up, I am not comfortable with my skills to touch the low level implementation. 3) Availability of documentation for FluentNHibernate is much than that of NHibernate. I would like to have a place to go when I hit a hard wall.
NHibernate: Currently, I am using naked Nhibernate xml to do the mapping. To be honest, working with XML gives me massive headaches. Literally, I have to keep myself from the impulsion of just throwing away the .hbm.xml files and grab ActiveRecord or FluentNHibernate several times a day.
So, here is my dilemma: Should I go with my heart of "Just get this damn thing done!"; Or, should I follow the "Good practice guideline" to suffer the pain now and get relatively easy time later on?
Any comments?
Please note that any classes related to an ORM should not necessary be treated as "business object" classes or exposed to your UI. They should be considered part of your data layer. This pattern is not really unique to ActiveRecord. In general, you want your business layer to know as little as possible regarding the fact that there is an ORM beneath it, and you don't want your UI to know about your data layer. You also want to consider DTOs.
Fluent NHibernate solves the problem of having weakly typed XML which can be error prone to refactor.
While there can be downsides of adopting something like ActiveRecord, it seems like an appropriate solution in your case.
The best reason to use .hbm.xml files is if you are going to code generate them from your database (using something like CodeSmith). Hand coding the .hbm.xml files is rarely the best option.