Search code examples
c#sql-servernhibernatefluent-nhibernate

Why is Nhibernate creating a FK for a ReferencesAny?


I create the Database from the mappings. And I have a ReferenceAny that is creating a constraint that causes issues on the updates of a table.

I simplified the code, but these are my classes:

public interface IInterfaceA
{
    int Id { get; }
}

public class ClassA
{
    public virtual int Id { get; protected set; }
    public virtual IList<ClassC> Items { get; set;  }
}

public class ClassB
{
    public virtual int Id { get; protected set; }
    public virtual IList<ClassC> Items { get; set;  }
}

public class ClassC
{
    public virtual int Id { get; protected set; }
    public virtual IInterfaceA Parent { get; set; }
}

These are my mappings:

public class ClassAMapping : ClassMap<ClassA>
{
    protected ClassAMapping()
    {
        Id(x => x.Id);
        HasMany(x => x.Items).KeyColumn("parent_id")                
                .Where(string.Format("parent_type = '{0}'", typeof(ClassA).Name))
                .Inverse()
                .Cascade.AllDeleteOrphan();

    }   
}

public class ClassBMapping : ClassMap<ClassB>
{
    protected ClassBMapping()
    {
        Id(x => x.Id);
        HasMany(x => x.Items).KeyColumn("parent_id")                
                .Where(string.Format("parent_type = '{0}'", typeof(ClassB).Name))
                .Inverse()
                .Cascade.AllDeleteOrphan();

    }   
}

public class ClassCMapping : ClassMap<ClassC>
{
    protected ClassCMapping()
    {       
        Id(x => x.Id);
        ReferencesAny(x => x.Parent)
                .IdentityType<int>()
                .MetaType<string>()
                .EntityTypeColumn("parent_type")
                .EntityIdentifierColumn("parent_id")        
            .AddMetaValue<ClassA>(typeof(ClassA).Name)
            .AddMetaValue<ClassB>(typeof(ClassB).Name);
    }   
}

I got the script for the FK that is being created:

ALTER TABLE [dbo].[ClassCTable]  WITH CHECK ADD  CONSTRAINT [FKA72ABA15F7EB0FA9] FOREIGN KEY([parent_id])
REFERENCES [dbo].[ClassBTable] ([Id])

When I inset items linked to ClassA sometimes I get an error when the Id conflicts with the ClassB.

Why is the FK being created? Am I using the ReferenceAny wrong? Is there at least a way to Nhibernate not to create the FK?


Solution

  • Silly me! I just noticed I forgot to tell the HasMany not to create the FK, I was puzzled because it was creating just one FK, but Of course they are conflicting that is why I just get one.

    So the ClassA and ClassB mapping should look like this:

    public class ClassAMapping : ClassMap<ClassA>
    {
        protected ClassAMapping()
        {
            Id(x => x.Id);
            HasMany(x => x.Items).ForeignKeyConstraintName("none").KeyColumn("parent_id")                
                    .Where(string.Format("parent_type = '{0}'", typeof(ClassA).Name))
                    .Inverse()
                    .Cascade.AllDeleteOrphan();         
        }   
    }
    
    public class ClassBMapping : ClassMap<ClassB>
    {
        protected ClassBMapping()
        {
            Id(x => x.Id);
            HasMany(x => x.Items).ForeignKeyConstraintName("none").KeyColumn("parent_id")                
                    .Where(string.Format("parent_type = '{0}'", typeof(ClassB).Name))
                    .Inverse()
                    .Cascade.AllDeleteOrphan();         
        }   
    }