8 Stimmen

NHibernate (3.1.0.4000) NullReferenceException bei Verwendung von Query<> und NHibernate Facility

Ich habe ein Problem mit NHibernate, für das ich anscheinend keine Lösung finden kann. In meinem Projekt habe ich eine einfache Entität (Batch), aber wann immer ich versuche, den folgenden Test auszuführen, erhalte ich eine Ausnahme. Ich habe versucht, ein paar verschiedene Möglichkeiten, eine ähnliche Abfrage durchzuführen, aber fast identische Ausnahme für alle (es unterscheidet sich in der LINQ-Methode ausgeführt wird).

Der erste Test:

[Test]
public void QueryLatestBatch()
{
    using (var session = SessionManager.OpenSession())
    {
        var batch = session.Query<Batch>()
            .FirstOrDefault();

        Assert.That(batch, Is.Not.Null);
    }
}

Die Ausnahme:

System.NullReferenceException : Object reference not set to an instance of an object.
at NHibernate.Linq.NhQueryProvider.PrepareQuery(Expression expression, ref IQuery query, ref NhLinqExpression nhQuery)
at NHibernate.Linq.NhQueryProvider.Execute(Expression expression)
at System.Linq.Queryable.FirstOrDefault(IQueryable`1 source)

Der zweite Test:

[Test]
public void QueryLatestBatch2()
{
    using (var session = SessionManager.OpenSession())
    {
        var batch = session.Query<Batch>()
            .OrderBy(x => x.Executed)
            .Take(1)
            .SingleOrDefault();

        Assert.That(batch, Is.Not.Null);
    }
}

Die Ausnahme:

System.NullReferenceException : Object reference not set to an instance of an object.
at NHibernate.Linq.NhQueryProvider.PrepareQuery(Expression expression, ref IQuery query, ref NhLinqExpression nhQuery)
at NHibernate.Linq.NhQueryProvider.Execute(Expression expression)
at System.Linq.Queryable.SingleOrDefault(IQueryable`1 source)

Diese geht jedoch vorbei (mit QueryOver<>):

[Test]
public void QueryOverLatestBatch()
{
    using (var session = SessionManager.OpenSession())
    {
        var batch = session.QueryOver<Batch>()
            .OrderBy(x => x.Executed).Asc
            .Take(1)
            .SingleOrDefault();

        Assert.That(batch, Is.Not.Null);
        Assert.That(batch.Executed, Is.LessThan(DateTime.Now));
    }
}

Die Verwendung der QueryOver<>-API ist gar nicht so schlecht, aber ich bin etwas verblüfft, dass die Query<>-API nicht funktioniert, was irgendwie traurig ist, da die First()-Operation sehr prägnant ist und unsere Entwickler LINQ wirklich mögen.

Ich hoffe wirklich, dass es eine Lösung für dieses Problem gibt, da es seltsam erscheint, wenn diese Methoden bei einem so einfachen Test versagen.

EDIT

Ich verwende Oracle 11g, meine Mappings werden mit FluentNHibernate durchgeführt, das über Castle Windsor mit der NHibernate Facility registriert ist. Wie ich schon schrieb, funktioniert die Abfrage perfekt mit der QueryOver<> API, aber nicht über LINQ.

11voto

Siewers Punkte 22116

Es gibt ein Problem mit der aktuellen Implementierung der LINQ-Erweiterungsmethoden für NHibernate 3.1.0.4000, die zusammen mit NHibernate Facility 2.0RC (und früheren Versionen) verwendet werden (siehe: https://nhibernate.jira.com/browse/NH-2626 und Diskussion hier: http://groups.google.com/group/castle-project-devel/browse_thread/thread/ac90148a8d4c8477 )

Die Lösung, die ich im Moment verwende, besteht darin, die von NHibernate bereitgestellten LINQ-Erweiterungsmethoden einfach zu ignorieren und sie selbst zu erstellen. Es sind wirklich nur Einzeiler:

public static class NHibernateLinqExtensions
{
    /// <summary>
    /// Performs a LINQ query on the specified type.
    /// </summary>
    /// <typeparam name="T">The type to perform the query on.</typeparam>
    /// <param name="session"></param>
    /// <returns>A new <see cref="IQueryable{T}"/>.</returns>
    /// <remarks>This method is provided as a workaround for the current bug in the NHibernate LINQ extension methods.</remarks>
    public static IQueryable<T> Linq<T>(this ISession session)
    {
        return new NhQueryable<T>(session.GetSessionImplementation());
    }

    /// <summary>
    /// Performs a LINQ query on the specified type.
    /// </summary>
    /// <typeparam name="T">The type to perform the query on.</typeparam>
    /// <param name="session"></param>
    /// <returns>A new <see cref="IQueryable{T}"/>.</returns>
    /// <remarks>This method is provided as a workaround for the current bug in the NHibernate LINQ extension methods.</remarks>
    public static IQueryable<T> Linq<T>(this IStatelessSession session)
    {
        return new NhQueryable<T>(session.GetSessionImplementation());
    }
}

Wenn ich dann eine LINQ-Abfrage durchführen muss, verwende ich einfach session.Linq<EntityType>() anstelle von session.Query<EntityType> .

Ich hoffe, es hilft jemandem, der sich in der gleichen Situation wie ich befindet.

0voto

Siewers Punkte 22116

Ich habe das Folgende gefunden: http://groups.google.com/group/castle-project-users/browse_thread/thread/5efc9f3b7b5d6a08

Offenbar gibt es ein Problem mit der aktuellen Version der NHibernate Facility und NHibernate 3.1.0.4000.

Ich schätze, ich muss einfach auf eine Lösung warten :)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X