One-to-one relations within nhibernate can be lazyloaded either \"false\" or \"proxy\". I was wondering if anyone knows a way to do a lazy one-to-one mapping.
I work
Lazy loading of one-to-one isn't supported unless the association is mandatory. See here for the reasoning.
It boils down to the fact that in order to decide if the other side of the relationship exists (N)Hibernate has to go to the database. Since you've already taken the database hit, you might as well load the full object.
While there are cases where hitting the DB just to see if the related object exists without actually loading the object makes sense (if the related object is very "heavy"), it isn't currently supported in NHibernate.
As far as I know, there isn't a non-hacky way to lazy load a one-to-one. I hope I'm wrong, but last time I checked it was the case.
After reading the answers here, I´ve manage to get it to work. I´m just going to add this example because I´m using a One to One relation with Constrained= False and because it´s a Mapping by Code Example
Two Classes:
public class Pedido:BaseModel
{
public virtual BuscaBase Busca { get; set; }
}
public class BuscaBase : BaseModel
{
public virtual Pedido Pedido { get; set; }
}
Mappings:
public class PedidoMap : ClassMapping<Pedido>
{
public PedidoMap()
{
Id(x => x.Id, x => x.Generator(Generators.Identity));
ManyToOne(x => x.Busca, m =>
{
m.Cascade(Cascade.DeleteOrphans);
m.NotNullable(true); m.Unique(true);
m.Class(typeof(BuscaBase));
});
}
}
public class BuscaBaseMap : ClassMapping<BuscaBase>
{
public BuscaBaseMap()
{
Id(x => x.Id, x => x.Generator(Generators.Sequence, g => g.Params(new { sequence = "buscaefetuada_id_seq" })));
OneToOne(x => x.Pedido, m =>
{
m.Lazy(LazyRelation.NoProxy);
m.Constrained(false);
m.Cascade(Cascade.None);
m.Class(typeof(Pedido));
});
}
}
Note: I was Using for the one-to-one mapping m.PropertyReference(typeof(Pedido).GetProperty("Busca"));
but this does't work for the lazy loading. You have to specify the relation using the Class
A quick brief about the Constrained = False used in here, the "Pedido" object might not exist in "BuscaBase" object.
There is way thought. It's described here in details :
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="NHibernateTest" namespace="NHibernateTest">
<class name="Person" >
<id name="PersonID" type="Int32">
<generator class="identity" />
</id>
<property name="LastName" type="String" length="50" />
<property name="FirstName" type="String" length="50" />
<many-to-one name="Photo" class="PersonPhoto" />
</class>
<class name="PersonPhoto">
<id name="PersonID" type="Int32">
<generator class="foreign">
<param name="property">Owner</param>
</generator>
</id>
<property name="Photo" type="BinaryBlob" />
<one-to-one name="Owner" class="Person" constrained="true" />
</class>
</hibernate-mapping>
I tried the example used by Artem Tikhomirov above. I kept getting an error that the Photo column does not exist. After looking at this, I figured out that the mapping was off a little. When I changed the many-to-one mapping to specify the column name like this:
many-to-one name="Photo" column="PersonID" class="PersonPhoto" unique="true"
I got it to work. I hope this helps someone :o)