NHibernate实体松散耦合

时间:2010-03-04 11:31:49

标签: nhibernate fluent-nhibernate nhibernate-mapping icriteria

假设我有一个名为MyItem的实体。它可以包含在许多“父母”中,例如SomeCollection和SomeOtherCollection。因为它可以包含在许多父母中,并且因为我不希望MyItem知道父母,所以我想在MyItem中没有引用父母的任何属性。

因为像SomeCollection这样的父母可以包含许多MyItems,所以我觉得我需要在从父母那里获取孩子时需要某种分页。这将使我无法在SomeCollection中引用MyItems的属性。懒惰是否加载,它总是“全有或全无”(对吧?)。

我确实需要在MyItem实体和它们的父级之间使用一些引用,但是以数据库中的映射表的形式。

问题:

  • 如何为此创建映射? 我可以有映射,还是应该有 关系保持在业务中 而不是逻辑?
  • 我如何查询 MyItem实体存在于哪个中 SomeCollection?我是否可以使用ICriteria只进行一次数据库访问?

2 个答案:

答案 0 :(得分:1)

<强> Many-to-One
父包含属性Child,孩子可能与多个父母链接。

class Parent
{
    public virtual MyItem Child { get; set; }
}

<class name="Parent">
    <many-to-one name="Child" column="MyItemId" />
</class>

<强> Many-to-Many with a join table
父母包含一系列儿童,儿童可能与几个父母有联系。

class Parent
{
    public virtual IList<MyItem> Children { get; set; }
}

<class name="Parent">
    <bag name="Children" table="parent_myitem">
        <key column="parentid" />
        <many-to-many class="MyItem" column="MyItemId" />
    <bag>
</class>

Criteria Querying

// find Parent with child named "foo".
DetachedCriteria.For<Parent>()
    .CreateAlias("Child", "c")
    .Add(Restrictions.Eq("c.Name", "foo"));

// find Parent with particular child
DetachedCriteria.For<Parent>()
    .Add(Restrictions.Eq("Child", child ));


// find Parent with one of children named "foo".
DetachedCriteria.For<Parent>()
    .CreateAlias("Children", "c")
    .Add(Restrictions.Eq("c.Name", "foo"));

// find a "page" of children for a parent
DetachedCriteria.For<Parent>()
    .Add(Restrictions.Eq("Id", parent.Id ))
    .CreateAlias("Children", "c")
    .SetFirstResult( 1041 )
    .SetMaxResults( 20 )
    .GetExecutableCriteria( session )
    .List<MyItem>();

通过在第一次访问时使用延迟加载整个子集合,然后在后续“页面”上索引到它,可以或可以不更有效地完成最后一个查询。这取决于您的数据和使用情况。

除非我先前知道儿童收藏品是巨大的,否则我会先去懒惰的载重路线。如果时间和profiling显示出严重的缓慢,那么我会切换到Criteria方法。

答案 1 :(得分:0)

我有一个像你这样的案子。我有Configuration类,可以是全局配置,项目特定配置或用户特定配置。我做的是这个:

  1. 我像往常一样将父母映射到所有可能的父母(除了全局,这意味着适用于所有父母,所以没有父母)
  2. < class name="ConfigurationDomain" table="configuration">  
        < property name="ProjectId" column="project_id" type="int" insert="false" update="false" />  
        < property name="UserId" column="user_id" type="int" insert="false" update="false" />  
        < many-to-one name="Project" column="project_id" lazy="false" />  
        < many-to-one name="User" column="estimator_id" lazy="false" />
    < /class>  
    
    1. 我将配置映射为每个可能的父母的集合
    2. < class name="UserDomain" table="user">  
          < set name="ConfigurationList" lazy="true" cascade="all-delete-orphan">  
            < key column="user_id" />  
            < one-to-many class="ConfigurationDomain" />  
          < /set>  
      < /class>  
      
      < class name="ProjectDomain" table="user">  
          < set name="ConfigurationList" lazy="true" cascade="all-delete-orphan">  
            < key column="project_id" />  
            < one-to-many class="ConfigurationDomain" />  
          < /set>  
      < /class>
      

      就像那样,它对我有用。如何访问ID为55的用户的配置是这样的:

      我不使用someUser.ConfigurationList,因为它很慢。我只映射父级,以便我可以在HQL中执行此操作(它更快):

      select c from ConfigurationDomain c where c.UserId=55
      

      要获得全局配置,我会这样做:

      select c from ConfigurationDomain c where (c.UserId IS NULL) and (c.ProjectId IS NULL)
      

      经过反思,我认为如果你决定使用HQL,你甚至可以删除集合映射。

      注意:我在NHibernate的早期使用过Criteria,但后来我发现HQL对我来说有点强大,其他人可能对此有不同看法。