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?
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();
}
}