1
votes

So I've been doing some work with NHibernate, and while what I have seen is mostly great, one thing is a little frustrating. If I try to query for some objects and there is a mapping problem in or with the hbm file, often there is no indication that there is a mapping problem, it just returns no results.

A simple example is if I forget to set the hbm file as an embedded resource, and then do a session.Query<Variable>().ToList(), there is no indication that there is no mapping for Variable, it just returns an empty list.

Is there any way to tell NHibernate to throw an exception or otherwise indicate that there is a problem with the mapping(s) in situations like this?

This does result in an exception:

_session.Get<Variable>(1) 

But these do not:

_session.Query<Variable>().Where(e => e.VariableId == 1).ToList()

_session.CreateCriteria(typeof(Variable)).Add(Restrictions.Eq("VariableId",1)).List<Variable>();

Hopefully it's something that I'm doing wrong, or something that can be configured, otherwise it will probably be a deal-breaker for using NHibernate. I can catch these things in my own unit tests relatively easy, but I can just see this becoming a festival of bugs when other developers start touching it.

1
I am surprised it doesn't throw an exception. Does it also fail silently if you use QueryOver? - Vadim
Yes, I just tried QueryOver and it has the same behavior. - Gerald
I'm downloading the source code to take a look now. The glory of Open Source. - Gerald
Something tells me that there is something not right in your project. By default NHibernate throws a MappingException with a "No persister for: entity" message. example - Vadim
Interestingly _session.Get<Variable>(1) does throw an exception, but _session.Query<Variable>().Where(e => e.VariableId == 1).ToList() does not. I think the difference may be that .Get really depends on there being an id mapping. - Gerald

1 Answers

1
votes

After doing a bit of digging through the code, I suspect you are right. Unmapped classes don't throw an exception on a List.

https://github.com/nhibernate/nhibernate-core/blob/master/src/NHibernate/Impl/SessionImpl.cs#L1869

            string[] implementors = Factory.GetImplementors(criteria.EntityOrClassName);
            int size = implementors.Length;

            CriteriaLoader[] loaders = new CriteriaLoader[size];
            ISet<string> spaces = new HashSet<string>();

            for (int i = 0; i < size; i++)
            {
                loaders[i] = new CriteriaLoader(
                    GetOuterJoinLoadable(implementors[i]),
                    Factory,
                    criteria,
                    implementors[i],
                    enabledFilters
                    );

                spaces.UnionWith(loaders[i].QuerySpaces);
            }

Note how if there are no implementors that are returned by Factory.GetImplementors, no error is generated, but nothing is done. Hence why you are seeing an empty list come back.

If we look at SessionFactoryImpl.GetImplementors we see that at no point is an exception thrown if no implementor is found. Just an empty array of implementors is returned.

So potentially there needs to be a check that if no implementors are returned by Factory.GetImplementors, a MappingException needs to be thrown.