We are using NHibernate as our ORM framework.
We have a need to persist classes we load at run time. We do that according to metadata they come with, that holds names and types of the data they have.
In order to build the tables for them at run time, we use the SchemaExport class from the NHibernate ToolSet API.
We wanted to ask two questions:
Is there a way to make NHibernate do all the actual creations in one roundtrip to the DB instead of a roundtrip per table?
In order to use the SchemaExport tool are building a dynamic string that represents a mapping file from a template we keep. Is there a better way to do this? Maybe even without a mapping string?
Ad 2.
If I understand you correctly, you don't want to use hbm mappings, right? Have you considered using Fluent NHibernate? (http://fluentnhibernate.org/)
Related
What are the proper steps to design and implmement a NHibernate data layer ?
Should I include a step to let NHibernate to generate the schema defintion rather than coding the schema by myself ?
It all depends whether you are starting from scratch or not. For new projects I use NHibernate to create the schema for me. For existing projects that I want to switch to NH I usually do the db changes manually. You need to be a little careful though in regards to your mapping and the db you are using. If you do not use the correct mapping with the correct db mapping you might have performance issues, as well as objects might update themselves without you knowing and when you flush the session your db will be updated.
In regards to using an actual data layer I usually use the Automatic Transaction Management & the NHibernate Facility from the Castle project. You can also make your own configuration builder for the NHibernate Facility so that it works with Fluent NHibernate as well.
That's a very open question.
Regarding the schema generation, yes, it's usually better to let NHibernate generate it.
For architectures based on NHibernate, you can check Sharp Architecture, Effectus and uNhAddIns
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.
We have been suggested to use NHibernate for our project. But the point is our application will only be retrieving the data from the database so are there any benefits of using NHibernate in this scenario?
One more thing, what is the query execution plan in NHIbernate does it support something like prepared statements or the so called pre complied statements.?
I agree to the answers above, but there is one more reason for using nhibernate: Your completely independend of the underlaying database system. You can switch from mysql to oracle and the only thing you have to do, is to change the settings. the access to the database stays exactly the same.
NHibernate is useful is you need to map data from a database table into a .NET class. Even if you're only doing select queries, it still might be useful if you need to pass the data objects to a client tier (web page, desktop app, etc.) for display. Working with plain objects can be easier than working with a DataSet or other ADO.NET data class in a presentation layer.
NHibernate does have the ability to parse/pre-compile queries if you put them in the mapping file.
The benefit for using NHibernate in a read only scenario is that you would not need to map the results of queries back to .net objects as the runtime would do this for you. Also, it provides a more object oriented query syntax (you can also use LINQ), and you can take advantage of lazy loading.
I don't believe NHibernate can use prepared statements unless you are having it call stored procedures.
Simple question, hopefully with a simple answer. I was under the impression I should create my tables and then use the map files to map my POCO classes to the database objects. After following some tutorials, I have this code in my Test SetUp:
new SchemaExport(_configuration).Execute(false, true, false, false);
Which, obviously, create the table structure as defined in the mappings, so I'm confused.
You need the mapping files for SchemaExport.
Ideally you write / design your classes first, write the mapping files afterwards. When writing mapping files, you are designing the database tables at the same time. SchemaExport just creates the schema from the mapping files where all the information is usually available.
SchemaExport is highly recommendable, even if it is a bit "hidden" in the docs.
It is better to have only one place to change, in your case you make changes in your classes and your db is automagically updated - do you expect anything better?
Sometimes you write new code for existing database, so you have to create (or have) database first, then need to prepare mappings manually.
EDIT:
I am using Fluent NHibernate, so this can be done fully automatically, not sure in different environments.
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.