Question

Is it possible to delete all data in the database using NHibernate. I want to do that before starting each unit test. Currently I drop my database and create it again but this is not acceptable solution for me.

==========================================================

Ok, here are the results. I am testing this on a database (Postgre). I will test CreateSchema(1), DanP solution(2) and apollodude217 solution(3). I run the tests 5 times with each method and take the average time.

Round 1 - 10 tests
(1) - ~26 sec
(2) - 9,0 sec
(3) - 9,3 sec

Round 2 - 100 tests
(1) - Come on, I will not do that on my machine
(2) - 12,6 sec
(3) - 18,6 sec

I think that it is not necessary to test with more tests.

Was it helpful?

Solution

Personally, I use a stored procedure to do this, but it may be possible with Executable HQL (see this post for more details: http://fabiomaulo.blogspot.com/2009/05/nh21-executable-hql.html )

Something along the lines of session.Delete("from object");

OTHER TIPS

I'm using the SchemaExport class and recreate the schema before each test. This is almost like dropping the database, but it's only dropping and recreating the tables. I assume that deleting all data from each table is not faster then this, it could even be slower.

Our unit tests are usually running on Sqlite in memory, this is very fast. This database exists only as long as the connection is open, so the whole database is recreated for each test. We're switching to Sqlserver by changing the build configuration.

I do not claim this is faster, but you can do something like this for each mapped class:

// untested
var entities = MySession.CreateCriteria(typeof(MappedClass)).List<MappedClass>();
foreach(var entity in entities)
    MySession.Delete(entity);  // please optimize

This (alone) will not work in at least 2 cases:

  1. When there is data that must be in your database when the app starts up.
  2. When you have a type where the identity property's unsaved-value is "any".

A good alternative is having a backup of the initial DB state and restoring it when starting tests (this can be complex or not, depending on the DB)

Re-creating the database is a good choice, especially for unit testing. If the creation script is too slow you could take a backup of the database and use it to restore the DB to an initial state before each test.

The alternative would be to write a script that would drop all foreign keys in the database then delete/truncate all tables. This would not reset any autogenerated IDs or sequences however. This doesn't seem like an elegant solution and it is definitely more time consuming. In any case, this is not something that should be done through an ORM, not just NHibernate.

Why do you reject the re-creation option? What are your requirements? Is the schema too complex? Does someone else design the database? Do you want to avoid file fragmentation?

Another solution might be to create a stored procedure that wipes the data. In your test set up or instantiate method run the stored procedure first.

However I am not sure if this is quicker than any of the other methods as we don't know the size of database and number of rows likely to be deleted. Also I would not recommend deploying this stored procedure to the live server for safety purposes!

HTH

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top