nhibernate 中的一对一关系可以延迟加载“假”或“代理”。我想知道是否有人知道一种方法来进行懒惰的一对一映射。
我通过使用映射到私有字段的惰性集并让公共属性返回该集的第一个结果,制定了一个技巧来实现相同的结果。它有效,但不是最干净的代码......
提前致谢!
nhibernate 中的一对一关系可以延迟加载“假”或“代理”。我想知道是否有人知道一种方法来进行懒惰的一对一映射。
我通过使用映射到私有字段的惰性集并让公共属性返回该集的第一个结果,制定了一个技巧来实现相同的结果。它有效,但不是最干净的代码......
提前致谢!
除非关联是强制性的,否则不支持延迟加载一对一。请参阅此处了解原因。
归结为这样一个事实,即为了确定关系的另一方是否存在 (N)Hibernate 必须访问数据库。由于您已经对数据库进行了访问,因此您不妨加载完整的对象。
虽然在某些情况下访问数据库只是为了查看相关对象是否存在而不实际加载对象是有意义的(如果相关对象非常“重”),NHibernate 目前不支持它。
据我所知,没有一种简单的方法可以延迟加载一对一。我希望我是错的,但上次我检查是这样的。
有办法的想法。这里有详细描述:
<?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>
我尝试了上面 Artem Tikhomirov 使用的示例。我不断收到照片列不存在的错误。看了这个之后,我发现映射有点不对劲。当我更改多对一映射以指定列名时,如下所示:
多对一名称=“照片”列=“PersonID”类=“PersonPhoto”唯一=“真”
我让它工作。我希望这对某人有帮助:o)
在这里阅读答案后,我设法让它工作。我只是要添加这个示例,因为我正在使用Constrained= False的一对一关系,并且因为它是通过代码示例进行映射
两个班:
public class Pedido:BaseModel
{
public virtual BuscaBase Busca { get; set; }
}
public class BuscaBase : BaseModel
{
public virtual Pedido Pedido { get; set; }
}
映射:
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));
});
}
}
注意:我使用的是一对一映射m.PropertyReference(typeof(Pedido).GetProperty("Busca"));
,但这不适用于延迟加载。您必须使用 Class 指定关系
简要介绍一下此处使用的 Constrained = False,“Pedido”对象可能不存在于“BuscaBase”对象中。
对我有用的是以下内容(与@Daniel 非常相似),但我发现有必要在映射的两端指定 LazyRelation.NoProxy。
public class Person
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual PersonDetails Details { get; set; }
public class PersonMap : ClassMapping<Person>
{
public PersonMap()
{
Id(x => x.Id, m =>
{
m.Generator(Generators.Native);
});
Property(x => x.Name);
OneToOne(x => x.Details, m =>
{
m.Lazy(LazyRelation.NoProxy);
m.Cascade(Cascade.Persist);
});
}
}
}
public class PersonDetails
{
public virtual int Id { get; set; }
public virtual string ExtraDetails { get; set; }
public virtual Person Person { get; set; }
public class PersonDetailsMap : ClassMapping<PersonDetails>
{
public PersonDetailsMap()
{
Id(x => x.Id, m =>
{
m.Generator(Generators.Native);
});
Property(x => x.ExtraDetails);
ManyToOne(x => x.Person, m =>
{
m.Lazy(LazyRelation.NoProxy);
m.Unique(true);
m.NotNullable(true);
});
}
}
}
using var session = NhHelper.OpenSession();
var person1 = new Person();
person1.Name = "A";
var person1Details = new PersonDetails();
person1Details.ExtraDetails = "A details";
person1.Details = person1Details;
person1Details.Person = person1;
session.Save(person1);
//because of PersonMapping's Cascade.Persist it is not necessary to manually save person1Details object.
using var session = NhHelper.OpenSession();
foreach(var person in session.Query<Person>()) {
Console.WriteLine(person.Name); //<-- does not load PersonDetails unless it's property is accessed
}