views:

603

answers:

2

Im just starting to work with NHibernate. I've setup a simple many-to-many scenario using Products and Suppliers as follows:

<class name="Product" table="Products">
    <id name="Id">
      <generator class="guid" />
    </id>
    <property name="Name" />

    <bag name="SuppliedBy" table="ProductSuppliers" lazy="true">
      <key column="ProductId" foreign-key="FK_ProductSuppliers_ProductId" />
      <many-to-many column="SupplierId" class="Supplier" />
    </bag>
</class>

<class name="Supplier" table="Suppliers">
    <id name="Id">
      <generator class="guid" />
    </id>
    <property name="Name" />

    <bag name="Products" table="ProductSuppliers" lazy="true" inverse="true">
      <key column="SupplierId"  foreign-key="FK_ProductSuppliers_SupplierId" />
      <many-to-many column="ProductId" class="Product" />
    </bag>
</class>

I'm now trying to wire the bags up to my domain objects. From reading the documentation I came up with (Using Iesi.Collections lib):

'In Product
Private _Suppliers As ISet = New HashedSet()
Public Overridable Property SuppliedBy() As HashedSet
    Get
        Return _Suppliers
    End Get
    Set(ByVal value As HashedSet)
        _Suppliers = value
    End Set
End Property

'In Supplier
Private _Products As ISet = New HashedSet()
Public Overridable Property Products() As HashedSet
    Get
        Return _Products
    End Get
    Set(ByVal value As HashedSet)
        _Products = value
    End Set
End Property

However, when I try and add a supplier to a product and call save I get the following error

Unable to cast object of type 'NHibernate.Collection.PersistentBag' to type 'Iesi.Collections.HashedSet

I've tried using all kinds of types, for example, ICollection and List(Of T) but I keep getting the equivalent error.

Unable to cast object of type 'NHibernate.Collection.Generic.PersistentGenericBag1[Domain.Supplier]' to type 'System.Collections.Generic.List1[Domain.Supplier]

What am I missing here?

A: 

The public property Supplier.Products needs to be of type ISet or ISet(Of Product).

Justice
+2  A: 

The documentation talks about creating a bag using an IList, or IList(of Entity) and constructing it with the List, or List(of Entity). (Section 6.2 of the NHibernate 1.2 Reference).

The Semantics of a bag do not match that of a Set which is that a Set can only have unique instances and a bag can have duplicate instances. As a fair comment a List does not match exactly the semantics of a bag either (a bag does not have an index) but it's close enough for NHibernate.

Your collection mapping should then be (using generics - take (of Supplier) out to remove generics:

'In Product
Private _Suppliers As IList(of Supplier) = New List(of Supplier)
Public Overridable Property SuppliedBy() As IList(of Supplier)
    Get
        Return _Suppliers
    End Get
    Set(ByVal value As IList(of Supplier))
        _Suppliers = value
    End Set
End Property
Michael Gattuso
Thanks very much! Works perfectly
Adam Pope