fluent-nhibernate icon indicating copy to clipboard operation
fluent-nhibernate copied to clipboard

Component That References Another Entity Can Cause Foreign Key Exception

Open rmabraham opened this issue 7 years ago • 6 comments

After updating to Nhibernate 5.0 from Nhibernate 3.1.0.4 and Fluent Nhibernate 2.1.0 from Fluent Nhibernate 1.2.0.712 the following issue started occurring.

I have an object Container which contains a list of Parents. Parents contains a COMPONENT object with a reference to another StringObject object. There are the following tables:

  1. Container
  2. Parent - Contains the Component as well.
  3. StringObject

If I create a Container with two parents and the first parent has a Component and the second doesn't everything works. But If the first has not component and the second doesn't I get a foreign key exception.

Nhibernate doesn't work properly with components. If it isn't a component but a regular domain mapped class to it's own table everything works.

rmabraham avatar Mar 15 '18 13:03 rmabraham

Here is Console APP that shows the issue:


using System;
using System.Collections.Generic;
using FluentNHibernate.Mapping;
using NHibernate;
using NHibernate.Tool.hbm2ddl;

namespace NhibernateReplicateForeignKeyBug
{
    class Program
    {
        private static string connectionString = string.Empty; //PUT YOUR CONNECTIONSTRING

        static void Main(string[] args)
        {
            ISessionFactory sessionFactory = CreateTables();
            var session = sessionFactory.OpenSession();

            using (ITransaction transaction = session.BeginTransaction())
            {
                try
                {
                    var EmptyParent = new Parent();
                    var ParentWithComponentWithObjectRef = new Parent
                    {
                        ComponentWithObjectRef = new ComponentWithObjectRef
                        {
                            StringObjectRef = new StringObject
                            {
                                Name = "TestName"
                            }
                        }
                    };
                    Container containerThatBreaks = new Container
                    {
                        Parents = new List<Parent> { EmptyParent, ParentWithComponentWithObjectRef}
                    };
                    Container containerThatWorks = new Container
                    {
                        Parents = new List<Parent> { ParentWithComponentWithObjectRef, EmptyParent}
                    };
                    session.Save(containerThatBreaks);
                    transaction.Commit();
                    Console.Out.WriteLine("Works!");
                }
                catch(Exception e)
                {
                    transaction.Rollback();
                    Console.Out.WriteLine("BROKEN!");
                    Console.Out.WriteLine(e);
                }
                Console.ReadLine();
            }
        }
        public static ISessionFactory CreateTables()
        {
            ISessionFactory sessionFactory;
            sessionFactory = FluentNHibernate.Cfg.Fluently.Configure()
                .Database(
                    FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2008
                        .ConnectionString(connectionString)
                )
                .Mappings(m =>
                {
                    m.FluentMappings.AddFromAssemblyOf<ParentMap>();
                })
                .ExposeConfiguration(cfg => new SchemaExport(cfg).Create(true, true))
                .BuildSessionFactory();
            return sessionFactory;

        }
    }

    #region Domain

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

        public virtual IList<Parent> Parents { get; set; }
    }

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

        public virtual ComponentWithObjectRef ComponentWithObjectRef { get; set; }

    }


    public class ComponentWithObjectRef
    {
        public virtual StringObject StringObjectRef { get; set; }
    }

    public class StringObject
    {
        public virtual Guid Id { get; set; }
        public virtual string Name { get; set; }
    }


    #endregion

    #region Mappings

    public class ContainerMap : ClassMap<Container>
    {
        public ContainerMap()
        {
            Id(x => x.Id);
            HasMany(x => x.Parents)
                .Cascade.All();
        }
    }

    public class ParentMap : ClassMap<Parent>
    {
        public ParentMap()
        {
            Id(x => x.Id);
            Component(x => x.ComponentWithObjectRef, c =>
            {
                c.References(y => y.StringObjectRef)
                    .ForeignKey()
                    .Cascade.All();
            });
        }
    }

    public class StringObjectMap : ClassMap<StringObject>
    {
        public StringObjectMap()
        {
            Id(x => x.Id);
            Map(x => x.Name);
          
         //   ComponentWithObjectRef(x => x.ComponentWithObjectRef, c =>
         //   {
         //       c.References(y => y.StringObjectRef)
         //           .ForeignKey()
         //           .Cascade.All();
         //   });
        }
    }

    #endregion
}

`

rmabraham avatar Mar 15 '18 13:03 rmabraham

Also posted on Nhibernate: https://github.com/nhibernate/nhibernate-core/issues/1616

rmabraham avatar Mar 15 '18 13:03 rmabraham

Hi,

Is there a chance someone could please have a look at this issue? This currently blocks me from upgrading to latest version ad it seems like a small fix.

Thanks, Guy

guyrocks avatar May 16 '18 08:05 guyrocks

Hi,

Is there a chance someone could please have a look at this issue? This currently blocks me from upgrading to latest version ad it seems like a small fix.

Thanks, Guy

guyrocks avatar Sep 14 '18 11:09 guyrocks