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,527
|
Comments: 51,163
Privacy Policy · Terms
filter by tags archive
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 | 156 words

You may have noticed that I like to play word games with code, so here is the Inversion of Control interface in Rhino Commons:

(Image from clipboard).png

The main goal is to be able to say:

ISender sender = (ISender)IoC.Container.Resolve("email");

The Initialize() method is called at application start, and will set everything up for the rest of the application. This class is to fetch the repositories, so I can generate a complex object graph and handle some interesting scenarios from the start, using generic decorators.

In the end, I didn't go with NHibernate / Transaction integration, for the simple reason that the Repository<T> and With.Transaction{} made them unnececary.

On Open Source

time to read 2 min | 285 words

You probably have heard that NDoc's lead developer, Kevin Downs, has announce that the NDoc is Dead. It also came up in the NHibernate devel mailing list, mostly as questions as to the viablity of open source.

I can't tell why other people are working on OSS, some do it for fun, others because it gives them tools or advantages for later on. It is rare that people are getting paid to work on Open Source Software. I know that I started this to sharpen my skills, and right now I am doing this because I like it and because it gives me the chance to do things that I like doing.

I am involved in a number of OSS projects, so I feel that I speak from experiance here. There are no guarantees of the amount of time that an OSS will go if you are not willing to invest time/money in it. If you do, you can either invest your time in fixing bugs, and send the patches to the project, where they are likely to be accepted.

The best way to influence the development of a product is to say what you want, and either help make it happen, or agree to pay for it. Even if your needs will not always fit the mainstream (you want to support NeverHeardOfDB, for instance) release, it can usually be fitted as a native extention to the product.

So, to cut it short, complaining about not getting what you want is not really going to help. You are getting your money's worth.

time to read 1 min | 124 words

I forgot to add that I am using a static forwarder class to get a better syntax, so I have this (after the change from RegisterSave()/RegisterDelete() to Save()/Delete() ).

(Image from clipboard).png

Another thing that I wanted to talk about was the FindAll()/FindOne() methods. While they have their overloads for working with ICriterion (and wait for a surprise there too), they also have overloads for queries.

Now, I believe that one of the responsabilities of good API is to encourage good code, so I don't have any overload which accept a literal query, instead, all the overloads accept the name of a named query, and its parameters.

time to read 4 min | 680 words

I'm currently building the API for the my Repository interface (I talked about it here). Here is what I have so far:

(Image from clipboard).png

Couple of things to note, I don't have Delete or Save methods, instead, I use RegisterSave() and RegisterDelete(), both of those make it clearer that a Unit Of Work is in action here. To make it more explicit (and to allow several repositories to use in a single Unit Of Work, I made the Unit Of Work an explicit concept:

(Image from clipboard).png

A sample code using this framework will look like this:

using (UnitOfWork.Start())

{

    With.Transaction(delegate

    {

        Customer customer = Repository<Customer>.Load(15);

        Order order = new Order();

        customer.Orders.Add(order);

        Repository<Order>.RegisterSave(order);

    });

}

Looking at the code, I don't know if RegisterSave() gives anything, to tell you the truth.

I'm using the commit only flush mode with NHibernate, which mean that if you are not commit the transaction, it will not be saved to the database. The problem is that then all my writing to the database will be inside a With.Transaction() block, which mostly make the Register***() mote.

Lectures Arsenal

time to read 2 min | 297 words

I am currently building a "lecture arsenal", which means that I should have a set of lectures that I can give at a moment notice. The idea came from Justin, who usually walks around with a portable projector, so he literally can be in the middle of a talk and start saying: "You know, I have a lecture of that. Give me three minutes and we can start" :-)

What I have at the moment is the following:

  • Inversion of Control & Dependency Injection - Introduction
  • Inversion of Control & Dependency Injection -
  • Using Mocks For Testing – Basic
  • Using Mocks For Testing – Advanced
  • Introduction to Object Relational Mapping – Nhibernate & Active Record
  • Building a web site using Active Record
  • Complex scenarios for using OR/M - Taking design patterns into the database layer.
  • MonoRail: An MVC web framework for .Net

Anything else that you think that I am qualified to talk about? I thought about:

  • Ranting about things that I don't like in ASP.Net

But I don't think that this will be a very good one :-)

FUTURE POSTS

No future posts left, oh my!

RECENT SERIES

  1. RavenDB Cloud (2):
    26 Nov 2024 - Auto scaling
  2. Challenge (75):
    01 Jul 2024 - Efficient snapshotable state
  3. Recording (14):
    19 Jun 2024 - Building a Database Engine in C# & .NET
  4. re (33):
    28 May 2024 - Secure Drop protocol
  5. Meta Blog (2):
    23 Jan 2024 - I'm a JS Developer now
View all series

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats
}