0

假设我有这个数据库架构

[User] -1----n-> [Resource] -1----n-> [ResourceVersion]

我想通过用户名在一次数据库往返中使用 Nhibernate 为用户选择此选项,但选择具有未来的 resourceVersions 不起作用。如何使用 Futures 在一次往返中补充集合的集合?我更喜欢 QueryOver 或 Criteria 而不是 HQL。我正在使用 nHibernate 4.0。

public virtual User GetUserResources(string username)
  using (ISession session = GetSession())
  {
    Resource resAlias = null;           
    User userAlias = null;

    var result = session.QueryOver(() => userAlias)
     .JoinQueryOver(x => x.Resources, () => resAlias)
     .JoinQueryOver(() => resAlias.Versions)
     .Where(() => userAlias.Login == username)
     .Future<User>(); //THIS DOESNT WORK


      var user = session.QueryOver<User>()
       .Fetch(x => x.Resources).Eager
       .Where(x => x.Login == username)
       .SingleOrDefault<User>();//with this i can select user and resources

      return user;
   }

映射:

USER:
<class name="User" table="[User]">
  <id name="Id" type="Int32">
    <generator class="identity" />
  </id>

  <property name="Name">
    <column name="Name" sql-type="varchar(100)" />
  </property>

  <property name="Email">
    <column name="Email" sql-type="varchar(255)" />
  </property>

  <property name="Login">
    <column name="Login" sql-type="varchar(50)" />
  </property>

  <property name="PasswordHash">
    <column name="PasswordHash" sql-type="varchar(100)" />
  </property>

  <property name="CreateDate">
    <column name="CreateDate" sql-type="datetime" />
  </property>

  <bag name="Resources" lazy="true" fetch="subselect" cascade="all-delete-orphan">
    <key column="UserResource"/>
    <one-to-many class="Resource" />
  </bag>
</class>

RESOURCE:
<class name="Resource" table="[Resource]" abstract="true">
  <id name="Id" type="Int64">
    <generator class="identity" />
  </id>

  <discriminator column="Type"
               not-null="true"
               type="String" />

  <bag name="Versions" cascade="all-delete-orphan" inverse="true" lazy="true" order-by="ActiveFrom DESC">
    <key column="ResourceId" not-null="true"/>
    <one-to-many class="Version"/>
  </bag>

  <subclass name="Resource1" discriminator-value="Res1" />

  <subclass name="Resource2" discriminator-value="Res2" />
</class>

VERSION:
<class name="Version" table="Version">

<id name="Id" type="long">
  <!--<column name="Id" sql-type="bigint"/>-->
  <generator class="identity" />
</id>
...
<many-to-one name="Resource"
             class="Resource"
             column="ResourceId"/>

 <property name="ActiveFrom">
   <column name="ActiveFrom" sql-type="datetime" />
 </property>

 <property name="ActiveTo">
   <column name="ActiveTo" sql-type="datetime"/>
 </property>
...

只有在 Visual Studio 中根据 Intelli Trace 执行的查询是这个:

SELECT this_.Id AS Id0_1_ , 
   this_.Name AS Name0_1_ , 
   this_.Email AS Email0_1_ , 
   this_.Login AS Login0_1_ , 
   this_.PasswordHash AS Password5_0_1_ , 
   this_.CreateDate AS CreateDate0_1_ , 
   resource2_.UserResource AS UserResource3_ , 
   resource2_.Id AS Id3_ , 
   resource2_.Id AS Id4_0_ , 
   resource2_.Type AS Type4_0_
FROM
   [User] this_ LEFT OUTER JOIN [Resource] resource2_
   ON this_.Id
      = 
      resource2_.UserResource
WHERE this_.Login    
        =
       @p0; 

在@p0 中是我传递给方法的用户名。完全没有版本的迹象,我觉得有点奇怪。

4

1 回答 1

0

您永远不会迭代未来返回的 IEnumerable,因此它永远不会执行它。我现在没有 NH 4.0,但以下可能有效

public virtual User GetUserWithResources(string username)
{
    using (ISession session = GetSession())
    {
      Resource resAlias = null;           

      return session.QueryOver<User>()
          .Where(user => user.Login == username)
          .Left.JoinQueryOver(x => x.Resources)
              .Left.JoinQueryOver(res => res.Versions)
          .TransformUsing(Transformers.DistinctRootEntity)
          .List<User>().SingleOrDefault();
    }
}
于 2015-02-10T12:52:42.373 回答