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,583
|
Comments: 51,214
Privacy Policy · Terms
filter by tags archive
time to read 2 min | 276 words

I had a problem in one of my applications, a Lucene search was returning more results than I wanted it to, and I wasn’t sure what was going on.

image

I pre marked the problematic line, but at the time, I had no idea why it is returning me all those extra results that had nothing to do with my queries. But since NH Prof gave me the full Lucene query text, I could take this and plug this into Luke.

image

Luke is the preferred tool to working with Lucene indexes, and running the query allowed me to play around and figure out what my problem was:

image

I was specifying that everything that is active MUST be returned, and everything that matches the query should be returned. Obviously, anything that is active (regardless of the rest of the query), must be returned.

In effect, this is similar to this SQL query:

select * from Entries
where IsActive = 1 or ( ... )

Once I figured that one out, it was pretty easy to fix the query to use MUST_NOT IsActive == False. But it would have been much harder without NH Prof.

Git renames

time to read 1 min | 160 words

One of the things that I like about Git is that I don’t have to think about operations that I make in my source. For example, I am working on the refactoring from NH Prof to ÜberProf, and I wanted to change the directories & project files. So I just went to explorer and renamed them.

Then I had to fix some namespaces references in the project file. It looks like this:

image

Notice that it capture both the rename and the content change?

You can also see how it looks in the log file:

image

Trying to do stuff like that with SVN is just PITA, with Git, I didn’t have to think about it.

time to read 6 min | 1051 words

My previous post relating to the business side of software seems to have met with positive reception, so here is another one. Let me know if you like it, or if you are interested in tech only content.

My father told me the secret for getting rich when I was just a little boy. It goes like this:

  • Buy cheap
  • Sell high

Unfortunately, I think that the .COM bubble made it clear that two yuppies in the living room don’t really add value that would make people buy from them.

So another strategy is needed.

One of the nicest past times is day dreaming.

Here are  a couple of nice dreams of getting rich quick:

If I make this widget, I can sell it for 50$. It is going to cost me 15,000$ to write it, but then every sell is practically free. I only need 300 sales to start earning money! If I sell just a 1,000 of them, I am going to earn 35,000$, and I can keep selling it forever.

It is like Manna from Heaven!

Or this one, which should be more familiar to anyone who isn’t in software:

I can go to the bank and get a mortgage on this house, they will cover 90% of the cost, so I only need to bring 15,000$ to get it. I pay 15,000$ and I have a 150,000$ assets in my hands. Mortgage payments is only 1,000$ a month for 15 years.

I can rent it for 1,500$, so the house covers the mortgage and I get 500$ a month for doing nothing. In 2.5 years, I get my original 15,000$ back, I still have the house, which is going to be worth 175,000$. I can sell it then and make 35,000$ profit!

It is like Manna from Heaven!

Now, I think that you can agree with me that those are pretty common thought patterns for people. They are also true. Think about it, wouldn’t you want to make 200% – 300% profit in a short amount of time?

Both schemes are valid ways to do so. Well, sort of.

The problem with the two schemes outlined above is that they have (in technical terms), absolutely no error handling. In fact, people paint the picture in terms so rosy that I suffer from pink overload.

Generally speaking, there are few things that hold true in business as well as this statement:

The higher the return on investment, the higher the risk.

With the real estate example, let us say that you have a month in which you have no renters, can you pay the mortgage? Out of your own pocket, that is. If not, you are likely to start spiraling down. And if you can pay the mortgage, can you pay city tax? What happen when you have a renter that is there, but doesn’t pay? You got legal costs to evict them.

And that is completely ignoring something like the current recession.

Just to give you some idea, you bought the house, rented it, and on the third month, the renter stopped paying rent and refuse to leave. It is going to take 30 days to evict them, and another 2 weeks to get a new renter. Your out of pocket expenses are going to be 2,000$ for the mortgage (for the two months in took to resolve things), another 1,500$ for the legal fees and probably at least two bottle of anti acid for your ulcer.

Oh, you might be able to recover some of the costs if you go after the renters (add more legal fees), but that assumes that they are able to pay, and the money is only going to show up sometimes in the future (if at all). In the meantime, you have better be able to cover the unexpected 3,500$ expense that just dropped in your lap.

With software, let us say that you quit your job to work on your widget. You spent a lot of time & effort on that, then you start selling it. In the first three months, 50 people buy it. Your underlying assumption about the number of buyers was overly optimistic. You are out of a job, out 12,500$ and feeling cheated.

Where it the Manna from Heaven?!

One of the things that I like about being in the army is that it thought me to plan. I can write an pretty good op plan, and that is close enough to a business plan. Most op plans have standard sections:

  • Goal
  • Mission
  • Our forces
  • Enemy forces
  • Obstacles
  • Dangers
  • Contingency plans
  • Abort

Whenever you are going to plan something big, you have to sit down and plan for the things that are going to bite you in the ass. I generally try to divide things into two categories. Contingency plans are for when the situation is recoverable. Abort is for when it isn’t, and I want to get out with as little damage as possible.

With software, that means that you have things like user studies, betas, etc. With real estate, I am not an expert so I am not going to comment. I would say that not getting in over your head is a good plan no matter what.

Final thoughts, figure out what your exit strategy is before you go in.

Figure out the cost of that exit strategy along with the cost of entering the game in the first place. That is the amount of money that you are putting on the table. And another final word of advice, that money is at risk, and the higher the return, the higher the risk. If you want to sleep well at night, make sure that you aren’t risking the money that you need to buy bread.

time to read 1 min | 189 words

A while ago I got a tattoo on my forearm (did I mention that you DevTeach is wild?). Here is how it looks like:

image

To preempt the nitpickers, this was my logo first, I reused it for other stuff afterward (including Rhino Mocks & NH Prof), but it is mine. I did not tattooed NH Prof’s logo.

So a while ago I was buying something in the supermarket and the clerk asked me why I had this tattoo. I told her that I like rhinos, and she said, but it is not a rhino.

Took me a while to realize that from her perspective, it looked like this:

image

Do you see it? You may need to tilt your head a bit to see it.

I guess that if need be, I can prove that I am OSS aficionado now.

time to read 5 min | 966 words

In order to integrate with an application, NH Prof requires that you’ll reference the appender dll and call NHibernateProfiler.Initialize(). For Linq To SQL, the process is similar, but you call LinqToSqlProfiler.Initialize().

This post describe the internal implementation of how the appender works. Well, that is a lie, I am actually using this post as a design document for the restructuring process that I am currently at to support multiple OR/M backends. The idea is to give some background information so people who want to integrate with the profiler can do so.

There are two sides for integrating an OR/M with NH Prof (by the way, I am taking suggestions about how to call the uber product, so far xProf is the winning candidate, and I am not sure that I like it).   The first part is actually integrating with the application, this is the job of the appender. It is responsible for capturing and sending the event stream from the profiled application to NH Prof. It is working under some fairly tight constraints:

  • Performance is a huge consideration, the overhead of the profiler on the profiled application side must be kept to a minimum.
  • The profiler may be started & stopped at any time, requiring application level support for reliable communication.
  • In the future, I want to be able to support production profiling, which is a whole can of worms in itself.

The second part of profiler integration is actually doing a lot of work on the profiler side. It means getting the event stream, parsing it, analyzing it, etc. This is actually fairly narrow part of the

Overall, the structure looks something like this:

image

At the top layer of the stack, we have integration with the actual OR/M. This is the point where the OR/M gets to output different

The output that we need is things like:

  • Session / Unit of Work Start & End notifications
  • Executed SQL (including parameters)
    • This should include capturing SQL executed as a result of lazy load operation.
  • Last query duration
  • Last query row count
  • Entity loaded (name + key)
  • Cached queries (for that matter, different types of queries, such as NHibernate Search’ queries)
  • Warning / Error messages about the OR/M usage
  • Statistics about the OR/M usage

The way NH Prof is dealing with this is quite simple, we have the following class:

public static class ProfilerIntegration
{
    public static void PublishProfilerEvent(
        Guid sessionId,
        string loggerName,
        string message
    );

    public static void PublishProfilerWarning(
        Guid sessionId,
        string message
    );

    public static void RegisterStatisticsSource(
      IStatisticsSource statsSource
    );
}

As you can see, the intent is to create an extremely simple integration point. The idea is that I don’t want to spend a lot of time integrating different OR/Ms. The only thing that I need to do if figure out how to get the OR/M to call those methods with the right information.

The format is textual and human readable. On the GUI side, NH Prof will take the information and start doing correlation and analysis. Part of the reason that I need to support different OR/Ms on the profiler side is that each of them has different ways of expressing those events, and I don’t want to try to do a single iota of extra work on the profiled application side if that can possibly be avoided.

Here is an example of how a minimal Linq To SQL implementation is using this infrastructure:

// this gets hooked into the l2s data context by black magic 
public class LinqToSqlAppender : IDisposable
{
    public Guid id = Guid.NewGuid();

    public LinqToSqlAppender()
    {
        ProfilerIntegration.PublishProfilerEvent(id, "LinqToSql.DataContext", "data context opened");
    }

    public void OnSqlExecuted(string sql)
    {
        ProfilerIntegration.PublisProfilerEvent(id, "LinqtoSql.SQL", sql);
    }

    public void Dispose()
    {
        ProfilerIntegration.PublishProfilerEvent(id, "LinqToSql.DataContext", "data context closed");
    }
}

With this in place, I have a very short turn around time in the actual profiler implementation.

time to read 2 min | 317 words

A forum question:

I have seen videos where you created a domain model using ActiveRecord in real-time... elaborate on when and how you move to using full Hibernate in more detail.

The problem with presentations such as the one described in the question is that they are cheating. Oh, I really do work things on the fly, but it is like asking me to type with my eyes closed (as I am doing right now, just to see if I can).

I can do that, but it doesn’t really say much about my typing skills. The type of models that I create live tend to be very simple ones, things that I have done for dozens and hundreds of times. Building a model live on stage looks impressive, especially since I insist of the people in the audience picking the model. But it really isn’t that hard.

That said, the actual question is more interesting, what should you choose? Active Record, Fluent NHibernate or mapping files?

I, personally, like using mapping files, they are simple, uncomplicated and expose everything that NHibernate can do. Active Record is nice if you want to put the persistence definition right there along the class definition. Another major advantage of Active Record is that it is working hard to infer things for you. It makes working with it very easy.

Fluent NHibernate is mapping using C#. I don’t quite see the point there, especially since in some things FN decided to diverge from the NHibernate terminology, but I get why people love it. The part about it that I simply adore is the auto mapping support. That is a great way of getting things started.

But usually, even if I am using Fluent NHibernate or Active Record, I am mostly using them as scaffolding. At some point, I’ll ask them to generate the HBM for me and start working with them.

That is me, however, your mileage might vary.

time to read 3 min | 460 words

Well, I was demoing how easy it is to add new features to NH Prof in a user group in JAOO today, and tomorrow I am doing my OR/M += 2 talk. Part of the things that I want to show is NHibernate Search, but the demo doesn’t really work unless I can point to NH Prof and show what is going on there.

I now consider output results to the console to be so 2005.

Here is the code that I am using for this post:

using (var s = factory.OpenSession())
{
    var posts = NHibernate.Search.Search.CreateFullTextSession(s)
        .CreateFullTextQuery<Post>("Title:NHibernate User.Name:ayende")
        .List<Post>();

    NHibernate.Search.Search.CreateFullTextSession(s)
        .CreateFullTextQuery<Post>("Title:NHibernate User.Name:ayende")
        .SetMaxResults(10)
        .List<Post>();

    foreach (var post in posts)
    {
        Console.WriteLine(post.Title);
    }
}

I had to make a small modification to NHibernate Search, to output the right information (which means that you can make this work with r1044 or up), but here is the result:

image

Notice that you can get not only the actual Lucene query text, but you also get the query duration and the number of returned results. The next query is NHibernate Search actually hitting the database to load the managed entities, after hitting the Lucene index to perform the actual search.

We can also generate some warnings on top of Lucene! As you can see here, we detect unbounded queries:

image

If you do specify a maximum number of entities to return, we are going to reflect that in the query directly:

image

We can also tell you if your Lucene index is out of date with respect to the database:

image 

Sweet, and is currently warming up in the oven, build 488 should have it.

JAOOOR/M += 2

time to read 1 min | 69 words

Just finished doing this presentation, I think it went very well, although I planned to do a 45 minutes session + 15 questions but I ended up hitting the session time limit without covering everything that I wanted.

You can get the source code that I have shown in the presentation here: http://github.com/ayende/Advanced.NHibernate

You can find the PDF of the presentation here: http://ayende.com/presentations.aspx

FUTURE POSTS

No future posts left, oh my!

RECENT SERIES

  1. Production postmorterm (2):
    11 Jun 2025 - The rookie server's untimely promotion
  2. Webinar (7):
    05 Jun 2025 - Think inside the database
  3. Recording (16):
    29 May 2025 - RavenDB's Upcoming Optimizations Deep Dive
  4. RavenDB News (2):
    02 May 2025 - May 2025
  5. Production Postmortem (52):
    07 Apr 2025 - The race condition in the interlock
View all series

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats
}