views:

35

answers:

2

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.

+1  A: 

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
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
@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
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
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
@James - thanks for the info; good to know!
DanP
+2  A: 

This should do it:

HasManyToMany(x => x.As)
  .ForeignKeyConstraintNames("no", "no");
James Gregory
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
It does do that too. It's the equivalent to the foreign-key attribute other people mentioned.
James Gregory