Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NHibernate <one-to-many>

How can I map these two classes?

public class LDAVehicle 
{
    public virtual int VehicleId { get; set; }
    public virtual string ChassisSeries { get; set; }
    public virtual string ChassisNumber { get; set; }

    public virtual List<LDAReading> Readings { get; set; }
}

public class LDAReading 
{
    public virtual int ReadingId { get; set; }
    public virtual DateTime IncomingDate { get; set; }
    public virtual DateTime ReadoutDate { get; set; }
    public virtual string Sender { get; set; }

    public virtual LDAVehicle Vehicle { get; set; }
}

Accually I have this xml:

<class name="LDAVehicle" table="Vehicle" schema="dbo" lazy="false">
    <id name="VehicleId">
        <column name="VehicleId" />
        <generator class="native"></generator>
    </id>
    <property name="ChassisSeries" column="ChassisSeries" not-null="false" />
    <property name="ChassisNumber" column="ChassisNumber" not-null="false" />

    <set name="Readings" table="Reading" fetch="join">
        <key foreign-key="VehicleId" />
        <one-to-many class="LDAReading" />
    </set>
</class>

<class name="LDAReading" table="Reading" schema="dbo" lazy="false">
    <id name="ReadingId">
        <column name="ReadingId" />
        <generator class="native"></generator>
    </id>
    <property name="IncomingDate" column="IncomingDate" not-null="true" />
    <property name="ReadoutDate" column="ReadoutDate" not-null="true" />
    <property name="Sender" column="Sender" not-null="false" />
    <many-to-one name="Vehicle" class="LDAVehicle" fetch="select" column="VehicleId" />
</class>

But I get an error:

An association from the table Reading refers to an unmapped class

like image 846
czupikawo Avatar asked Sep 30 '22 05:09

czupikawo


1 Answers

There are few improvements I would made to make it running

1) C#

If we map collections, they MUST be represented as interfaces, so NHibernate will be able to inject proxies... own implementation

public class LDAVehicle 
{
    public virtual int VehicleId { get; set; }
    public virtual string ChassisSeries { get; set; }
    public virtual string ChassisNumber { get; set; }

    //public virtual List<LDAReading> Readings { get; set; }
    public virtual IList<LDAReading> Readings { get; set; }
}

public class LDAReading 
{
    public virtual int ReadingId { get; set; }
    public virtual DateTime IncomingDate { get; set; }
    public virtual DateTime ReadoutDate { get; set; }
    public virtual string Sender { get; set; }

    public virtual LDAVehicle Vehicle { get; set; }
}

2) hbm

For mapping collection I would use bag (until NHibernate 4 is released with native use of System stuff, we would need to use iesi collection ... so <bag> is good enough now).

Also if propery name and column are same, we do not have to mention column.

Finally, all mappings are strongly LAZY now. This is simply the way which to go

<class name="LDAVehicle" table="Vehicle" schema="dbo" lazy="true"> // should be lazy
    <id name="VehicleId" column="VehicleId" generator="native" />  // simple id def

    <property name="ChassisSeries" not-null="false" /> // name is enough
    <property name="ChassisNumber" not-null="false" /> // if column is the same

    // IList and <bag> go work together
    // also profit from lazy loading, 
    //  batch size fetching and inverse mapping
    <bag name="Readings" lazy="true" inverse="true" 
                         batch-size="25" cascade="all-delete-orphan"> 
        <key column="VehicleId" />
        <one-to-many class="LDAReading" />
    </bag>
</class>

<class name="LDAReading" table="Reading" schema="dbo" lazy="true">
    <id name="ReadingId" generator="native" />

    <property name="IncomingDate" not-null="true" />
    <property name="ReadoutDate"  not-null="true" />
    <property name="Sender"       not-null="false" />

    <many-to-one name="Vehicle" class="LDAVehicle" column="VehicleId" />
</class>

3) be sure that both mapping are Emebedded Resources. If one of these is not found... not embedded... the exception as in the question is thrown... Also, both files should/must have suffix .hbm.xml

More reading:

  • inverse mapping
  • Ayende - NHibernate is lazy, just live with it
  • batch size fetching
like image 124
Radim Köhler Avatar answered Oct 18 '22 13:10

Radim Köhler