Skip to content

Incorrect fetch of Many-to-Many relation #3290

Closed
@mm-rpodstawa

Description

@mm-rpodstawa

Recently I've upgraded NH to version 5.4.2 and I've found an issue related to many-to-many relation. Here is a test case:

    public class Entity
    {
        public virtual Guid Id { get; set; }

        public virtual string Name { get; set; }
        
        public virtual ICollection<Entity> Children { get; set; } = new HashSet<Entity>();

        public virtual ICollection<Entity> Parents { get; set; } = new HashSet<Entity>();
    }



    public class EntityMapping : ClassMapping<Entity>
    {
        public EntityMapping()
        {
            Id(x => x.Id, map => map.Generator(Generators.GuidComb));

            Property(
                x => x.Name
            );

            Set(
                x => x.Children,
                v =>
                {
                    v.Table("OrganisationUnitParent_OrganisationUnitChildren");
                    v.Cascade(Cascade.None);
                    v.Inverse(true);
                    v.Key(x =>
                    {
                        x.Column("ParentOuId");
                        x.NotNullable(true);
                    });
                    v.Lazy(CollectionLazy.Lazy);
                    v.Fetch(CollectionFetchMode.Join);
                },
                h => h.ManyToMany(m => m.Column("ChildOuId"))
            );

            Set(
                x => x.Parents,
                v =>
                {
                    v.Table("OrganisationUnitParent_OrganisationUnitChildren");
                    v.Cascade(Cascade.All);

                    v.Key(x =>
                    {
                        x.Column("ChildOuId");
                        x.NotNullable(true);
                    });
                    v.Lazy(CollectionLazy.Lazy);
                    v.Fetch(CollectionFetchMode.Join);
                },
                h => h.ManyToMany(m => m.Column("ParentOuId"))
            );
        }
    }


        [Test]
        public void Test1()
        {
            var person = new Entity();
            person.Name = "pers";
            Session.SaveOrUpdate(person);
            var job = new Entity();
            job.Name = "job";

            Session.SaveOrUpdate(job);

            job.Children.Add(person);
            person.Parents.Add(job);
            Session.SaveOrUpdate(job);
            Session.SaveOrUpdate(person);
            Session.Flush();

            using (var newSession = _sessionFactory.OpenSession())
            {
///////1////////
                //this query causes the problem. If you comment it, this test will pass
                var allOUs = newSession
                    .QueryOver<Entity>()
                    .Fetch(SelectMode.Fetch, x => x.Children)
                    .Fetch(SelectMode.Fetch, x => x.Parents)
                    .TransformUsing(Transformers.DistinctRootEntity)
                    .List();
                
                var jobDb = newSession.Get<Entity>(job.Id);
                var personDb = newSession.Get<Entity>(person.Id);
                
                Assert.AreEqual(1, jobDb.Children.Count);

///////2////////
                Assert.AreEqual(1, personDb.Parents.Count);//because of this issue, here we have 0 instead of 1
                
                //now let's remove all members
                personDb.Parents.Clear();
                jobDb.Children.Clear();
                newSession.Update(personDb);
                newSession.Flush();
            }

            using (var newSession = _sessionFactory.OpenSession())
            {
                var jobDb = newSession.Get<Entity>(job.Id);
                var personDb = newSession.Get<Entity>(person.Id);
                Assert.AreEqual(0, jobDb.Children.Count);
                Assert.AreEqual(0, personDb.Parents.Count);
            }
        }

In this test personDb.Parents.Count (///////2////////) has no elements and should be 1 item. This is because of query above (///////1////////). If you comment this query, the test will pass.
This test works good in version 5.3, and in version v5.4.0+ it fails.

If you need more info, please let me know.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions