views:

376

answers:

3

I am using: NHibernate, NHibernate.Linq and Fluent NHibernate on SQL Server Express 2008. I am selecting an entity using a predicate on a referenced property (many-one mapping). I have fetch=join, unique=true, lazy-load=false. I enabled the log4net log and when any such query executes it logs two identical SQL queries. Running the query returns one row, and when I attempt to use the IQueryable.Single extension method it throws the exception stating there is more than one row returned. I also tried running the query using the standard IQuery.UniqueResult method with the same result, it ends up logging and actually running the query twice, then throwing an exception stating that there were multiple rows, however running the actual query in management studio returns only one result. When I disable logging I receive the same error.

The entities and mappings are declared as follows (proper access modifiers and member type variance are implied)

class User
{
    int ID;
    string UserName;
}

class Client
{
    int ID;
    User User;
    Person Person;
    Address Address;
}

class UserMap : ClassMap<User>
{
    public UserMap()
    {
       Id(x => x.ID);
       Map(x => x.UserName);
    }
}

class ClientMap : ClassMap<Client>
{
    public ClientMap()
    {
       Id(x => x.ID);
       References(x => x.User).Unique();
       ...
    }
}

Then I invoke a queries such as the following:

ISession s = GetNHibernateSession();

...

var client = s.Linq<Client>().SingleOrDefault(x => x.User.ID = 17);

or

var client = s.Linq<Client>().Where(x => x.User.ID = 17);

or

var client = s.CreateQuery("from Client as c where c.User.ID = 17").UniqueResult<Client>();

In all cases executes two identical queries. When I enable lazy load, the client is again loaded using two queries, however upon accessing a member, such as Person, only one additional query is executed.

Is this possibly a result of Fluent generating an improper mapping? Or SQL Server Express edition not being used properly by NHibernate?

A: 

NHibernate doesn't have any trouble with SQL Express, I've used it fairly extensively. Similarily, it's unlikely Fluent NHibernate is generating invalid mappings in this simple scenario (but not unheard of).

A shot in the dark, but I believe NHibernate reserves the name Id as an identifier name, so when it sees Id in the query it knows to just look at the foreign key instead of the actual joined entity. Perhaps your naming of ID instead of Id is throwing it off?

James Gregory
A: 

You could try using the excellent NHibernate profiler for a more detailed view of what is happening. It comes with a 30 day trial license and while in Beta there is a discount on the full license cost

Keith Bloom
+2  A: 

The problem was caused by another mapping I had declared. I had a class inheriting from Client which had an associated mapping. This is what caused NHibernate to query twice. I noticed this because when using Linq() it returned the subclass, not Client itself. This particular instance of inheritance and mapping was a design flaw on my part and was the root of the whole problem!

eulerfx