代码之家  ›  专栏  ›  技术社区  ›  Casper

NHibernate:如何在一对一映射上启用延迟加载

  •  15
  • Casper  · 技术社区  · 17 年前

    我想出了一个方法,通过使用映射到私有字段的惰性集,并让公共属性返回该集的第一个结果,来实现相同的结果。它可以工作,但不是最干净的代码。。。

    提前谢谢!

    5 回复  |  直到 17 年前
        1
  •  20
  •   Sean Carpenter    17 年前

    除非关联是强制性的,否则不支持一对一的延迟加载。看见 here

    归根结底,为了确定关系的另一端是否存在(N),Hibernate必须转到数据库。既然您已经访问了数据库,那么不妨加载完整的对象。

        2
  •  4
  •   James Gregory    17 年前

    据我所知,没有一种非黑客方式可以一对一地延迟加载。我希望我是错的,但上次我检查的时候是这样的。

        3
  •  4
  •   Brandon    17 年前

    思想是有办法的。它被描述了 here 详情如下:

    <?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> 
    
        4
  •  2
  •   David Yates    17 年前

    this ,我发现地图有点不对劲。当我更改多对一映射以指定列名时,如下所示:

    多对一name=“Photo”column=“PersonID”class=“PersonPhoto”unique=“true”

        5
  •  0
  •   Daniel    7 年前

    读完这里的答案后,我设法使它起作用。 约束=假

    两类:

    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")); 但这对延迟加载不起作用。必须使用类指定关系

        6
  •  0
  •   krdx    5 年前

      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
    }
    
    • NHibernate 5.3.5