Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# - NHibernate unable to cast NHibernate.Collection.Generic.PersistentGenericSet to System.Collections.Generic.IList

For some reason, NHibernate is telling me it can't convert NHibernate.Collection.Generic.PersistentGenericSet[Ingredient] to System.Collection.Generic.IList[Ingredient], when I try to get the data from the database. This is a simplfied version of my class mapping/implementation:

public class Product {
    protected Product() { };

    public virtual Name { get; set; }
    public virtual IList<Ingredient> {
        get { return new List<Ingredient>(ingredients).AsReadOnly(); }
        protected set { ingredients = value; }
    }

    private IList<Ingredient> ingredients = new List<Ingredient>();
}

--

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
    <class name="LanchesAdmin.Core.Domain.Product, LanchesAdmin.Core" table="product" >
        <id name="ID" generator="identity">
            <column name="id" not-null="true" />
        </id>

        <property name="Name" column="name" length="64" not-null="true" />

        <set name="Ingredients" table="ingredient" fetch="join" lazy="true" inverse="true">
            <key column="product_id" />
            <one-to-many class="LanchesAdmin.Core.Domain.Ingredient, LanchesAdmin.Core" />
        </set>
    </class>
</hibernate-mapping>

I've seen several related questions, but they all tell me to use IList, and that's exactly what I'm doing.

like image 665
rmobis Avatar asked Oct 04 '12 12:10

rmobis


3 Answers

The reason is that you are using a set. And PersistentGenericSet<T> simply doesn't implement the IList<T> interface.

I think you should simply make the property of type IEnumerable<Ingredient>.
This solves two problems:

  1. You get rid of the error you mentioned
  2. The API of your class directly communicates that consumers of your class aren't allowed to add ingredients via that property.
like image 58
Daniel Hilgarth Avatar answered Sep 30 '22 00:09

Daniel Hilgarth


Either change type of the property to ISet from IList.

Or change mapping from <set> to <list>.

like image 35
Euphoric Avatar answered Sep 30 '22 00:09

Euphoric


Do you want a list, bag or set? Your domain model contains a IList<T> but you've mapped it as a <set>.

Either change your mapping to a <bag> or <list> or change your domain model to use a ISet<T>.

like image 40
Roger Avatar answered Sep 30 '22 02:09

Roger