SQL Server table-relations necessary with NHibernate? - sql

This may be a really silly question, but I've found no answer on google/bing...
If I already use NHibernate for persistence with SQL Server, why should I then create all the table-relations on the database-schema?
I'm just wondering because it seems to create all the relations, altough I already have defined them in the NHibernate-mapping.
Best regards,
Daniel Lang

If the schema was generated via NHibernate, it already established all the relations on a schema level. Now, if NHIbernate was not used in the generation of the schema, you would still be advised to establish them, because there's always the chance that a coding mistake could lead to database operations which would break the relationship rules, but NHibernate is ignoring due to a bug in the code.
An example of this would be a relationship with a Not Null constraint. If NHibernate is configured incorrectly, it may very well try to update an object and set the relation to Null (say, instead of deleting it), which would be really hard for you to debug without the correct relations and/or an NHibernate debugging tool like NHProf.

Related

NHibernate and code first

Do you use SchemaExport and SchemaUpdate in real applications? Initially, you create model and then generate schema? Does it work? Or, you use it only for tests...
Usually, I create db (using visual studio database project) and then mappings and persistent classes or EF entities using designer. But now, I want to try code first approach with Fluent NHibernate.
I have researched SchemaExport and SchemaUpdate and found some issues. For example, update doesn't delete db objects, creates not null columns like nullable if table exists, doesn't generate primary key on many-to-many tables and so on. It mean that I have to recreate db very often. But, what's about data? And, how to deploy changes to production db and so on...
I want to know do you really use code first and SchemaExport(SchemaUpdate) in your applications? May be you can give me some advices...
I use SchemaUpdate in production. It is safe precisely because it never does destructive operations like deleting columns. However, it is not a comprehensive solution for updating your database. If you use it you will still have to supplement it with script to update your schema to do things like deleting (as you mention), indexes, changing column type, adding table data, etc. But SchemaUpdate covers the 90% case for me.
The only downside I've discovered is that over time it seems to occasionally add duplicate foreign-key constraints to my table.
One more thing: you should run SchemaUpdate manually from a build tool, not your app itself. It is not safe to give your application the rights to modify your db schema!
I use SchemaUpdate/SchemaExport for rapid evolution of my model, but they are not a replacement for a database migration tool. As you mention, data cannot be migrated in a sensible manner in many cases. The tool does not have enough context. (e.g. How can you automatically migrate a FullName column to FirstName/LastName?) I answered a similar question here where I discuss db migration tools in the context of NHibernate.
NHibernate, ORM : how is refactoring handled? existing data?
Yes, you can use these in real applications; I do.
Of course, almost all the work happens in that first go. My practice has been to create a separate project that references the mappings in my main project assembly and handles database creation and the initial data import, if any.
Once the project is in production, I usually unload that project from the solution, but keep it around for reference or if I ever need to switch from create scripts to update scripts.
As for the way NHibernate creates the database, you have to do a little more specification in your Fluent mappings than you otherwise might. I like to specify null/not null, foreign key constraint names, etc. to have maximum control over the way the database gets created.
I don't think you'd ever want to use automapping in this scenario.
Just with any generating code whether it be poco generation from a tool or database generation as in your question, it will probably get you 80% of the way there. From there it would be wise to tweak it the other 20% to add your indexes and any other performance tweaks to get it just right.

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.

Getting Started with Fluent NHibernate

I'm trying to get into using Fluent NHibernate, and I have a couple questions. I'm finding the documentation to be lacking.
I understand that Fluent NHibernate / NHibernate allows you to auto-generate a database schema. Do people usually only do this for Test/Dev databases? Or is that OK to do for a production database? If it's ok for production, how do you make sure that you're not blowing away production data every time you run your app?
Once the database schema is already created, and you have production data, when new tables/columns/etc. need to be added to the Test and/or Production database, do people allow NHibernate to do this, or should this be done manually?
Is there any REALLY GOOD documentation on Fluent NHibernate? (Please don't point me to the wiki because in following along with the "Your first project" code building it myself, I was getting run-time errors because they forget to tell you to add a reference. Not cool.)
Thanks,
Andy
I've been using Fluent NHibernate Automapping for a few months now. I'm by no means an expert, but can take a stab at your questions...
FNH Automapping does indeed create DB schemas from POCO classes, including lists of other objects (this was the reason I chose NHibernate in the first place).
When you change schemas, you have to rerun the automapping, which does drop the whole database, unfortunately. In my case, it's not a big problem because I'm importing existing binary data files, so I just have to re-import my data every time the schema changes. I've read that there's some data migration support available with NHibernate, but have no experience with this. (BTW, Subsonic will do data migration, but it's automapping functionality is far more rudimentary - at least it was when I evaluated it a few months ago)
FNH documentation is one of my pet peeves - they have not even added Intellisense help on the method names, etc. (But they get really huffy when you point that out - ask me how I know!) I've made a couple of edits to the wiki when I could, but there's so much more that could be done there. The best approach is to start with a working example (i.e.
this one from Nikola Malovic, and post questions to the support form if (when!) you run into trouble. In general, I've found the FNH community pretty helpful, and have been able to work through all my difficulties. They've also fixed a couple of bugs I've found.
Overall, using FNH has been a huge win for my project - highly recommended!
I don't use Fluent, but I can help with classic NHibernate.
yes, the creation of the schema is very recommendable for production use (Schema Export). When you do this is up to you. For instance, you could create the database by an installer. You shouldn't drop existing databases, but this is a decision of you application.
I don't understand this question. Do you mean you need to upgrade an existing database to a new database schema? This is unfortunately something you need to implement yourself. NH can't do much about this, because it is very specific to you data and the changes you made. There is also a Schema Update or something like this, which is not recommended for production use.
I don't use Fluent, so I can't help here.

Linq to Sql and Non-PK, unique-FK relationship issues

I've recently been reading Louis Davidson's book on Sql Server Database Design and found it quite informative. I've picked up on alot of concepts that I didn't previously know alot (or anything) about. Primarily - I picked up on a way to set up database relationships that I hand't tried before.
Basically you use a surrogate key as the tables PK (an auto incremented id field) and then set up one or more Alternate Keys consisting of one or more Unique keys. Theese alternate kays would then be the values used for relationships (or the PK, if that makes more sense for the given relationship).
I remodelled an old database that was suffering from some data inconsitencies due to poor design to implement this, to me, new way of thinking.
On a database level it works great. Tha relationships function the way they're supposed to and the constraints are enforced in a consistent, reliable manner.
HOWEVER
I cannot get it to work properly in either the Entity Framework or in Linq to Sql classes. I read that in V1 of EF, it just flat out won't support this kind of relationship - so I moved to Linq to Sql to see if things would work out better. They seemingly did, as I got all the relationships automatically mapped out when I imported the classes from my database. The problem is that I can't save data to the database because of InvalidCastOperation exceptions as soon as I try to save data.
So I have a couple of questions:
Is this a limitation in Linq To Sql?
If so, is there a way to work around
it? Preferebly without implementing
sprocs for save, update and delete -
type safety is something I would
like to keep.
Is this way of designing database
relationships "correct" and/or a
good practice?
I hope someone can shed some light on this, as I'm getting quite frustrated about it. I can't really find any good material on the subject online - so hopefully someone here has an answer or can point me in the right direction.
Thanks alot!
EDIT - Solution.
What I ended up doing was this - I went back to using the Entity Framework in conjunction with a redesign of the database schema. I remodeled the relationships to rely on primary keys rather than alternate keys, in most cases. Where that was not an option - I made some modifications to the EF layout. I implemented the relationship that relied on the AK's - at which time EF complains. To get around that I had to delete the foreign key property on the many side of the relationship at which point EF accepts the relationship.
1) Yes.
2) If you can mark your alternate key as primary in the L2S model and unmark the real PK as PK then it will work.
3) From the db perspective there's nothing wrong, but as you have noticed it is not supported by L2S or EF. Personally I prefer to always have FKs pointing to the PK and only use AKs for lookups.

Would you use NHibernate for a project with a legacy database, which is partly out of your control?

For me the answer is currently: No, I would use iBatis, because NHibernate is a pain, when the database model and the object model are not in synch. If I don't have full control over the database I end up with a lot of work.
Why do I ask?
Well, first of all: I never used NHibernate. I just know it from the surface. I have read about the advantages of iBatis for legacy databases.
Second: Recently I had a discussion with someone who worked with Hibernate (jep, without 'N' before Hibernate). He told me that the ORM frameworks are now pretty advanced and advocated Hibernate. Since I was not interested in NHibernate, I didn't keep track of the recent developments.
Maybe I its time to rethink my answer, or not?
iBatis is certainly easy to map objects to legacy database systems.
More recently NHibernate 1.2 and 2.0 have a feature set that may make you rethink iBatis.
NHibernate works with composite keys, which can occur frequently in older databases, they aren't always pleasant to work with but support is there for this.
NHibernate can utilise Stored Procedures for CRUD operations on entities, also database views.
Collections can be custom stored procedures or SQL queries. Collections can use the property-ref attribute when the Foreign Key relationship doesn't map directly to the Primary Key on the other side.
Some of these features may take away from the performance/power of nhibernate, ie Lazy Loading with property-ref doesn't work (at all?), but is most cases there are reasons for this.
Other points: (which aren't really related to your legacy database but still can help decide on a technology choice)
The Nhibernate community appears much richer than the iBatis. I'm on both lists and the volume of support for NHibernate is quite large compared to the iBatis group. So support should be easier.
Also there is a growing amount of contrib/3rd party tools for NHibernate. Things like The NHibernate Profiler, the Nhibernate Query Analyzer, NHibernate Contrib, Fluent NHibernate to name a few.
Perhaps you can expand on what advantages you believe iBatis currently has. NHibernate has certainly been quite active recently and has gained many new features, a lot of which do assist in legacy/hard to modify schemas.
And to answer the question, yes we do use NHibernate with legacy databases that have awful relationships, composite keys, broken relationships. We still also have a small amount of code based on iBatis. We no longer write any more iBatis code though.
Yes, consider NHibernate. It's the gold standard for a reason. I have heard that iBATIS supports crazy mapping possibilities, but with NHibernate's IUserType you can map anything, even really strange columns.
#Ahmad, the entire point of ORM is to prevent a tight coupling between your objects and your schema. If you have this problem you're doing it wrong.
Also, with NHibernate there are plenty of options for custom queries, formula properties and stored procedures. HQL is extremely powerful and Criteria is flexible.
I think you'll be doing your clients a disservice if you don't at least spike NHibernate.
I've been using nHibernate in an existing application. I use it for all new development, I have no intention of porting the existing stuff over either there just isn't a compelling reason but for new stuff on the project it works great.
If you are going to port the code over then you should be able to change the database to match better with your domain model, without much impact (depending on how leaky your database is ie who access it). Changing the domain model would impact the application however.