TDD developer

June 21, 2009

NHibernate 2.1.0 beta 2

Filed under: .NET, nhibernate — makka @ 5:15 pm
Tags: ,

Today NHibernate team released version 2.1.0 beta 2

This version contains a fix for bug that cause some problem with MS Sql server execution plans (more details here).

Be carefull if you use an HQL query cause the actual parser is not still able to use the correct parameter type. I hope also this issue will be solved in the future versions but in the meantime you can use the solution I wrote in post linked above.

Technorati Tag: ,

April 19, 2009

LINQ to NHibernate

Filed under: .NET, nhibernate — makka @ 2:29 pm
Tags: , ,

This is a very great news for NHibernate!

Time for another update; it’s been a while since the last one. Good progress has been made on the new HQL AST Parser port from Hibernate, and it’s now in a state where it’s usable, passing the vast majority of the tests within the NHibernate test suite. Of those that are failing (around 8 out of over 1600), we are currently discussing on the developers group whether we will live with these minor breaking changes, or do continued work on the parser to get everything passing.

March 10, 2009

NHibernate queries & sql server execution plans

Filed under: .NET, nhibernate — makka @ 8:57 pm
Tags: , , ,

In these days I’m working with Andrea on a web application using ASP.NET & SQL Server . You should kwon that Andrea, is a SQL Server MVP, but fortunately is not a T-SQL taliban so he agree without hesitation when I proposed to use NHibernate to build our data access layer. When a tool can help us while building an application why not use it ?

As you can image a skilled DBA like Andrea can rapidly find a bottleneck in any query fired to a database. While writing a simple query using NHibernate API we noticed a strange behavior of NHibernate 2.0 with parameters. Here is the code we wrote:

using (ISession session = factory.OpenSession())
{
	//nvarchar(4)
	session.CreateQuery("from Region r where r.Description like :desc")
		.SetString("desc", "zon%")
		.List();

	//nvarchar(5)
	session.CreateQuery("from Region r where r.Description like :desc")
		.SetString("desc", "zone%")
		.List();
}

This code generates these two sql queries:


exec sp_executesql N'select region0_.RegionId as RegionId0_, region0_.RegionDescription as RegionDe2_0_ from Region region0_ where (region0_.RegionDescription like @p0 )',N'@p0 nvarchar(4)',@p0=N'zon%'

exec sp_executesql N'select region0_.RegionId as RegionId0_, region0_.RegionDescription as RegionDe2_0_ from Region region0_ where (region0_.RegionDescription like @p0 )',N'@p0 nvarchar(5)',@p0=N'zone%'

As you can see the parameter type is different in the two statements. This unfortunately cause SqlServer to generate two different exection plans. If you need the best performace you should avoid this behaviour. If you send to the database queries using the same parameter (type & size) SqlServer use his internal cache. You have already pay for it so why not to use it ?

I had the pleasure to discuss with Fabio Maulo about this topic (you can read here. The conversation is in italian). At the end I found this solution:

I edited my hibernate.cfg.xml file adding this node to the xml

<property name="prepare_sql">true</property>

and then I wrote this code:

using (ISession session = factory.OpenSession())
{

	//nvarchar(10)
	session.CreateQuery("from Region r where r.Description like :desc")
		.SetParameter("desc", "zoneh%", TypeFactory.GetStringType(10))
		.List();

	//nvarchar(10)
	session.CreateQuery("from Region r where r.Description like :desc")
		.SetParameter("desc", "neh%", TypeFactory.GetStringType(10))
		.List();
}

Now with this code NHibernate generates these two sql queries:

declare @p1 int
set @p1=1
exec sp_prepexec @p1 output,N'@p0 nvarchar(10)',N'select region0_.RegionId as RegionId0_, region0_.RegionDescription as RegionDe2_0_ from Region region0_ where (region0_.RegionDescription like @p0 )',@p0=N'zoneh%'
select @p1

declare @p1 int
set @p1=2
exec sp_prepexec @p1 output,N'@p0 nvarchar(10)',N'select region0_.RegionId as RegionId0_, region0_.RegionDescription as RegionDe2_0_ from Region region0_ where (region0_.RegionDescription like @p0 )',@p0=N'neh%'
select @p1

This is better cause the parameters length is always the same. Now your database will thank you for this! But wait you can still do something better.

If your database column type is a varchar and not nvarchar you can improve your code using a different SqlDbType. How ? Whit his code:

using (ISession session = factory.OpenSession())
{
	session.CreateQuery("from Region r where r.Description like :desc")
		.SetParameter("desc", "z%", TypeFactory.GetAnsiStringType(15))
		.List();

	session.CreateQuery("from Region r where r.Description like :desc")
		.SetParameter("desc", "za%", TypeFactory.GetAnsiStringType(15))
		.List();
}

Now the parameter type is a varchar and the size is always 15. Whit this latest improvement you remove a CONVER_IMPLICIT operation from your query execution plan (futher details here but in italian ). This cast operation cost something so if you don’t need it why to remove it ?

I hope this will help someone (dev & dba) in the future!

Blog at WordPress.com.