Skip to content

NullReferenceException is thrown when using Fetch #3288

@Madajevas

Description

@Madajevas

NullReferenceException in being thrown when trying to query with fetch and where condition on fetched data. This happens with v5.4.0+; v5.3.16 works without issues. Setup is a bit complex, hope that repro code bellow will explain it better.

using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Cfg;
using NHibernate;
using NHibernate.Util;
using FluentNHibernate.Mapping;
using NHibernate.Linq;
using NUnit.Framework;

public class Tests
{
    private ISessionFactory sessionFactory;

    [SetUp]
    public void Setup()
    {
        var config = Fluently.Configure()
            .Database(MsSqlConfiguration.MsSql2008.ConnectionString("Server=localhost;Database=test;User Id=sa;Password=Test4000;"))
            .Mappings(m => m.FluentMappings.AddFromAssemblyOf<Tests>())
            .BuildConfiguration();

        sessionFactory = config.BuildSessionFactory();
    }

    [Test]
    public void Test1()
    {
        using var session = sessionFactory.OpenSession();

        var entities = session.Query<TopEntity>()
            .Fetch(e => e.MiddleEntity)
            .Where(e => e.MiddleEntity.BottomEntities.Any(e => e.OneMoreEntity != null))
            .ToList();
    }
}

class TopEntity
{
    public virtual int Id { get; set; }
    public virtual MiddleEntity MiddleEntity { get; set; }
}
class TopEntityMap : ClassMap<TopEntity>
{
    public TopEntityMap()
    {
        Id(e => e.Id);
        References(e => e.MiddleEntity);
    }
}

class MiddleEntity
{
    public virtual int Id { get; set; }
    public virtual ISet<BottomEntity> BottomEntities { get; set; }
}
class MiddleEntityMap : ClassMap<MiddleEntity>
{
    public MiddleEntityMap()
    {
        Id(e => e.Id);
        HasMany(e => e.BottomEntities)
            .Table("BottomEntity")
            .Cascade.All()
            .KeyColumn("MiddleEntity_id").Not.KeyNullable()
            .Component(e => {
                e.ParentReference(x => x.MiddleEntity);
                e.References(x => x.OneMoreEntity);
            });
    }
}

class BottomEntity
{
    public virtual MiddleEntity MiddleEntity { get; set; }
    public virtual OneMoreEntity OneMoreEntity { get; set; }

    public override bool Equals(object? obj)
    {
        return (obj as BottomEntity)?.MiddleEntity.Id == MiddleEntity.Id;
    }

    public override int GetHashCode()
    {
        return MiddleEntity.Id.GetHashCode();
    }
}
class BottomEntityMap : ClassMap<BottomEntity>
{
    public BottomEntityMap()
    {
        CompositeId()
            .KeyReference(x => x.MiddleEntity, "MiddleEntity_id")
            .KeyReference(x => x.OneMoreEntity, "OneMoreEntity_id");
    }
}

class OneMoreEntity
{
    public virtual int Id { get; set; }
}
class OneMoreEntityMap : ClassMap<OneMoreEntity>
{
    public OneMoreEntityMap()
    {
        Id(e => e.Id);
    }
}

Tested with the following database schema:

drop table if exists TopEntity;
create table TopEntity
(
	id int primary key,
	MiddleEntity_id int not null
);

drop table if exists MiddleEntity;
create table MiddleEntity
(
	id int primary key
);

drop table if exists BottomEntity;
create table BottomEntity
(
	MiddleEntity_id int not null,
	OneMoreEntity_id int not null
);

drop table if exists OneMoreEntity;
create table OneMoreEntity
(
	id int primary key
);

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions