Oren Eini

CEO of RavenDB

a NoSQL Open Source Document Database

Get in touch with me:

oren@ravendb.net +972 52-548-6969

Posts: 7,589
|
Comments: 51,218
Privacy Policy · Terms
filter by tags archive
time to read 2 min | 201 words

After using it for a couple of days, I made the following improvements:

  • Added Eq() and IdIs() to many-to-one references, so now I can issue this statement:
    ICollection<Order> orders = Repository<Order>.FindAll( Where.Order.Customer.IdIs(15) );
    It seems like we are using this quite a bit in our applications, mainly from query strings.
  • Added support for VB.Net
  • Create a VS.Net Custom Tool, so now you wouldn't have to mess with the command line, just specify "NHibernateQueryGenerator" as the custom tool, and you are done.
  • Create an MSI installer for it, so it is really close to zero friction now.

You can get it here.

time to read 5 min | 881 words

Okay, it looks like I can track down fairly easily what books I read, when I read Working Effectively with Legacy Code, I wrote Rhino Mocks. Now I am reading Applying Domain-Driven Design and Patterns, and I wrote the NHibernate Query Generator.

So, what is this all about?

NHibernate has two major API for querying objects. The first one is called the query API, and uses HQL, a language similar to SQL but with OOP aspirations. The second is called the criteria API, and it is far simpler API, but it is also much easier to use.

Here is a simple example of using the criteria API using my Repository sample from yesterday:

ICollection<Customer> customersInLondon = Repository<Customer>.FindAll(Expression.Eq("City""London"));

Now, those of you that already knows me know that I have a passionate dislike to strings. I wrote a mock objects library because of this issue, so I may need physcological therapy in the future, but I hate strings.

Well, what do I do when there is something that I don't like? I fix it.

In this case, there where two main options, run time proxying and code generation.

Run time proxying is similar to what I do in Rhino Mocks, and it may look like this:

ICollection<Customer> customersInLondon = Repository<Customer>.FindAll(Expression.Eq(Expr.Of<Customer>().Name,"London"));

This has the disadvantages of being both ugly and complex, so I turned to the other route. I build a small application which takes an NHibernate mapping file (hbm.xml) file, and output a strongly typed query wrapper. The above query can now be used like this:

ICollection<Customer> customersInLondon = Repository<Customer>.FindAll(
   Where.Customer.City.Eq("London") );

This is much better, and of course that you get all the other nice things about the expression API (like Between, In, etc).

You can get it here, binaries only. Source would have to wait for a while, my subversion provider has run out of room. Note that the code it generates relies on a class called NamedExpression. The class is included in the binary, so just add it to your project and you are done.

I also added support for queries, since I didn't want to leave the other side of the API high and dry, it means that you can do this:

ICollection<Customer> customersInLondon = Repository<Customer>.FindAll(
    Queries.AllCustomersInCity, new Parameter("city""London"));

Here is a little FAQ

  • What does it generate:
    The tool generate strongly typed wrappers for each of the mapped entities and each of their properties. At the moment, is supports querying against properties, many-to-one, and ids.
  • How to make it work for all the files in a directory?
    Simply use the batch capabilities of the shell, like this:
    for %f in (*.hbm.xml) DO "NHibernate.Query.Generator.exe" %f D:\Queries
    This will run the tool over all the files in the directory, and output them all to the Queries dir.
  • How to make it work with ActiveRecord?
    You need to use the isDebug="true" flag in the configuration, and then point the tool to the resulting mapping files.
  • Can I get is as a custom tool for Visual Studio?
    It shouldn't be hard to do, but I don't have the time at the moment. Feel free to send me a patch for it when I release the code.
time to read 1 min | 78 words

I'm pretty ashamed to admit it, but I managed to foul up IEnumerator<T> for EntityDictionary<T,K>. I was very surprised to realize this, I assure you, I thought that at this point I could be trusted to handle a simple collection delegation, but apperantely this is not the case.

There is a new version which fix this issue, add some better error messages, etc. As usual, you can get it here.

time to read 2 min | 303 words

Don't ask about the version number, it just is. I haven't done an all-nighter in quite a while, and while it was fun to do, I'm not thinking very clearly right now. Here is the details about this release:

I finally got around to take a good hard look into NHibernate Query Analyzer (AKA: NQA). I haven't update it in a while, and that is a shame. There was an issue with query translations when using parameters that kept me from going forward for a long time. Today I bit the bullet and trace it through all the twists and turns along the way and found the problem.

Along the way I also solved the Nullables issue that I've not been able to fix since forever. I run into some very strange differences between 1.1 and 2.0 along the way. Up until now, I mostly developed NQA on 1.1, but now I did all the work in 2.0 and the issues highly annoying (see randon GC failure).

The new stuff is:

  • Working against NHibernate 1.0.2 (the latest and greatest).
  • Supports 2.0 and 1.1
  • Supports Nullables

The fun part is that I did all of that without opening the UI once. I'm pretty confident in my tests to be able to do this without stuff breaking. I'm too tired now to think, but in the background there is a gong that warns against temping Merphie, but what the hell.

You can get it here

time to read 1 min | 194 words

I'm trying to load this type using Type.GetType(string):

Nullables.NHibernate.NullableDateTimeType, Nullables.NHibernate, Version=1.0.2.0, Culture=neutral, PublicKeyToken=154fdcb44c4484fc

The Nullables.NHiberante is loaded in the assembly, but I keep getting Strong Name Is Required exceptions.

After spending way too much time on this, I figured out that I had added a reference to the NHibernate project, and that the Nullables.NHibernate library was looking for the NHibernate library (this is important, since the NHibernate project is not signed and the library is). I solve this, and I get a strange error about a Nullables.NullableInt32 could not be assigned to Nullables.NullableInt32. It this mismatched version thingie again.

I solve that one, and everything works. It's like magic. I just tested it on a second computer in both .net 2.0  and .net 1.1, it appears to work there as well, so there is something horribly wrong in the horizon and it is closing fast. I've better release something before it arrive.

time to read 2 min | 296 words

If you throw an exception on the finalizer thread, expect bad things to happen.

I just run into this issue where both TestDriven.Net and ReSharper Test Runner doesn't handle this issue. I would get a nasty error message from Windows telling me that this is a rouge application and none of my tests will continue to run.

The issue was that several of the tests were creating chain of objects, and the lower most object was a Component, which mean that it is disposable and finalizable. In the dispose method it called a dipose method on a mock object, but because the mock object was no longer in a valid state when the finalizer was called, an exception was thrown.

The fun part is that when I try to fix this, I find out that any exception from the test will cause the mock object to be invalid state and then the finalizer will kick in and dispose the object, which will call the mock, which will throw...

The really nice part is that running the test one by one will not expose this bug. It seems like the finalizer is not getting a chance to run in this case. But the moment you got several tests, it will kick in and kill the tests. It's just two tests, and to fix this I would need to open up a chain of seams in the objects, so for now I'm just calling GC.WaitForPendingFinalizers(). This at least will crash the tests predictably :-)

 

FUTURE POSTS

  1. RavenDB 7.1: The Gen AI release - 13 hours from now
  2. RavenDB and Gen AI Security - 4 days from now
  3. RavenDB & Distributed Debugging - 7 days from now
  4. RavenDB & Ansible - 12 days from now

There are posts all the way to Jul 22, 2025

RECENT SERIES

  1. RavenDB 7.1 (7):
    18 Mar 2025 - One IO Ring to rule them all
  2. Production postmorterm (2):
    11 Jun 2025 - The rookie server's untimely promotion
  3. Webinar (7):
    05 Jun 2025 - Think inside the database
  4. Recording (16):
    29 May 2025 - RavenDB's Upcoming Optimizations Deep Dive
  5. RavenDB News (2):
    02 May 2025 - May 2025
View all series

Syndication

Main feed ... ...
Comments feed   ... ...
}