Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NullReferenceException is thrown when using Fetch #3288

Closed
Madajevas opened this issue Apr 20, 2023 · 7 comments
Closed

NullReferenceException is thrown when using Fetch #3288

Madajevas opened this issue Apr 20, 2023 · 7 comments

Comments

@Madajevas
Copy link

Madajevas commented Apr 20, 2023

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
);
@bahusoid

This comment was marked as resolved.

@Madajevas

This comment was marked as resolved.

@bahusoid

This comment was marked as resolved.

@Madajevas

This comment was marked as resolved.

@fredericDelaporte
Copy link
Member

It seems likely to me it has the same root cause than #3290. May you try disabling detect_fetch_loops and setting max_fetch_depth to an appropriate, large enough value for your case? See bef3bb7 Configure method.

@bahusoid
Copy link
Member

It seems likely to me it has the same root cause than #3290.

Nope. Another regression from #2496 revealing old hql bug

@bahusoid
Copy link
Member

Fixed by #3314

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants