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

Fluent NHibernate:映射复杂的多对多(带有附加列)并设置fetch

  •  5
  • moribvndvs  · 技术社区  · 15 年前

    我需要一个流利的NHibernate映射,它将实现以下功能(如果没有其他功能,我还将使用适当的NHibernate XML映射并对其进行反向工程)。


    细节

    我在两个实体之间有一种多对多的关系: Parent Child

    这大概就是我定义类型的方式,至少是相关的部分(其中 Entity Id

    public class Parent : Entity
    {
        public virtual IList<ParentChildRelationship> Children { get; protected set; }
    
        public virtual void AddChildRelationship(Child child, int customerId)
        {
           var relationship = new ParentChildRelationship
                            {
                               CustomerId = customerId,
                               Parent = this,
                               Child = child
                            };
           if (Children == null) Children = new List<ParentChildRelationship>();
           if (Children.Contains(relationship)) return;
           relationship.Sequence = Children.Count;
           Children.Add(relationship);
        }
    }
    
    public class Child : Entity
    {
        // child doesn't care about its relationships
    }
    
    public class ParentChildRelationship
    {
        public int CustomerId { get; set; }
        public Parent Parent { get; set; }
        public Child Child { get; set; }
        public int Sequence { get; set; }
    
        public override bool Equals(object obj)
        {
           if (ReferenceEquals(null, obj)) return false;
           if (ReferenceEquals(this, obj)) return true;
           var other = obj as ParentChildRelationship;
           if (return other == null) return false;
    
           return (CustomerId == other.CustomerId
               && Parent == other.Parent
               && Child == other.Child);
        }
    
        public override int GetHashCode()
        {
           unchecked
           {
               int result = CustomerId;
               result = Parent == null ? 0 : (result*397) ^ Parent.GetHashCode();
               result = Child == null ? 0 : (result*397) ^ Child.GetHashCode();
               return result;
           }
        }
    }
    

    数据库中的表大致如下(假定主键/外键和语法):

    create table Parent (
       id int identity(1,1) not null
    )
    
    create table Child (
       id int identity(1,1) not null
    )
    
    create table ParentChildRelationship (
       customerId int not null,
       parent_id int not null,
       child_id int not null,
       sequence int not null
    )
    

    在访问Parent.Children时,NHibernate应该生成一个等价的查询:

    SELECT * FROM ParentChildRelationship rel LEFT OUTER JOIN Child ch ON rel.child_id = ch.id WHERE parent_id = ?

    好的,我有这样的映射:

    ParentMap : ClassMap<Parent>
    {
       public ParentMap()
       {
          Table("Parent");
          Id(c => c.Id).GeneratedBy.Identity();
          HasMany(c => c.Children).KeyColumn("parent_id");
        }
    }
    
    ChildMap : ClassMap<Child>
    {
       public ChildMap()
       {
          Table("Child");
          Id(c => c.Id).GeneratedBy.Identity();
       }
    }
    
    
    ParentChildRelationshipMap : ClassMap<ParentChildRelationship>
    {
       public ParentChildRelationshipMap()
       {
          Table("ParentChildRelationship");
          CompositeId()
                    .KeyProperty(c => c.CustomerId, "customerId")
                    .KeyReference(c => c.Parent, "parent_id")
                    .KeyReference(c => c.Child, "child_id");
          Map(c => c.Sequence).Not.Nullable();
        }
    }
    

    所以,在我的测试中,如果我想 myParentRepo.Get(1).Children parent.Children.Select(r => r.Child).ToList() ).

    SELECT * FROM ParentChildRelationship WHERE parent_id = 1 然后是一个 SELECT * FROM Child WHERE id = ? 每段关系中的每个孩子。我理解NHibernate为什么要这样做,但是我不知道如何设置映射以使NHibernate按照我上面提到的方式进行查询。

    1 回复  |  直到 15 年前
        1
  •  2
  •   Stefan Steinegger    14 年前

    我不明白为什么它不能像你那样工作,但我可以告诉你我将如何映射它:

    <class name="Parent">
    
        <id .../>
    
        <list name="Children" table="ParentChildRelationship">
            <key column="parent_id"/>
            <index column="Sequence"/>
    
            <composite-element>
                <property name="CustomerId"/>
                <many-to-one name="Child"/>
            </composite-element>
        </list>
    
    </class>
    
    <class name="Child">
        <id .../>
        <property .../>
    </class>
    

          <many-to-one name="Child" fetch="join" />