0

I got a polymorphic relationship like the following example:

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

Class B & C contining a List of A's:

public class B/C
{
    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<A> As { get; set; }
    public virtual SomeParent Parent { get; set; }
}

My goal are queries like

session.Linq<B>().Where(x => x.Parent == someParent && x.As.Contains(someA));

Currently I configured a Many-To-Many relation between B => A and C => A using a shared link table because I want to have all my links in one table. In this examle NH shema export creates 4 tables, A, B, C and ChildToA.

HasManyToMany(x => x.As)
            .AsBag()
            .Table("XX_ChildToA")
            .ParentKeyColumn("Child_ID")
            .ChildKeyColumn("A_ID")
            .Cascade.All()

This works fine as long as you use only one the child types because shema export generates a foreign key restricting the "Child_ID" to IDs of whatever table it hits first while exporting (B in this case).

var b = session.Get<B>(id);
b.As.Add(someA);
tx.Commit(); // works fine

var c = session.Get<C>(id);
c.As.Add(someA);
tx.Commit(); // crashes because of FK constraint

Can I stop FluentNHibernate from creating this FK? While I searched google for this problem I noticed HBM samples with foreign-key="no" attributes in many-to-one relationships. So NHibernate should be able to solve this, right? However I would like to keep my fluent mappings because I can create a generic base mapping class for all my child types this way and currently all our mappings are FNH mappings.

Zebi
  • 8,682
  • 1
  • 36
  • 42

2 Answers2

2

This should do it:

HasManyToMany(x => x.As)
  .ForeignKeyConstraintNames("no", "no");
James Gregory
  • 14,173
  • 2
  • 42
  • 60
  • Thats it! Thank you very much. I thought the ForeignKeyConstraintNames Method defines the naming pattern so the keys are not named like random hex values ;) – Zebi Aug 18 '10 at 07:01
  • It does do that too. It's the equivalent to the foreign-key attribute other people mentioned. – James Gregory Aug 18 '10 at 08:22
  • ForeignKeyConstraintNames("no", "no") does not work (at least in Fluent NHibernate 1.3.0.717 which I am currently using in one of my projects). The good thing is that ForeignKeyConstraintNames("none", "none") does :) – Christian Myksvoll Jul 10 '12 at 06:36
  • That sounds like a change in the underlying NHibernate behaviour. Good catch though, thanks. – James Gregory Jul 11 '12 at 01:11
1

I'm not entirely familiar with FluentNHibernate, but I'm assuming you could set this custom attribute on your mapping for the collection using something like:

.SetAttribute("foreign-key", "no")

DanP
  • 6,310
  • 4
  • 40
  • 68
  • Can not verify it until tomorrow at work however I am relatively sure there is no SetAttribute method on the mapping. I already used this method on the configuration object to set the batch size and my first thought was to do it the same way on the mapping definition. – Zebi Aug 17 '10 at 19:12
  • @Zebi: I believe you're right; upon reviewing the FluentNHibernate docs it doesn't look like you can use .SetAttribute() on a collection mapping... – DanP Aug 17 '10 at 20:44
  • Just got the idea to point the automapper at a slightly different testcase (b+c get an IChild interface, A gets list of IChild) and observe what happens. It should result in an Many-to-Any mapping... maybe it gets the mappings right this way round. – Zebi Aug 17 '10 at 20:53
  • 1
    The `SetAttribute` methods were removed about a year ago, you should favour the method calls instead (`SetAttribute("foreign-key", "xxx")` -> `ForeignKey("xxx")` etc...) – James Gregory Aug 17 '10 at 23:40