【问题标题】:Nhibernate Queryover multi level modelNhibernate Queryover 多级模型
【发布时间】:2015-02-09 02:35:15
【问题描述】:

假设我有这个数据库架构

[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 中是我传递给方法的用户名。完全没有我觉得有点奇怪的版本迹象。

【问题讨论】:

  • 有什么不好的?
  • 它根本不向数据库询问任何包含版本的查询。资源上的版本集合也会引发延迟初始化异常。
  • 你能显示你的映射文件吗?
  • 确定我为问题添加了映射。

标签: c# sql nhibernate nhibernate-futures


【解决方案1】:

您永远不会迭代未来返回的 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();
    }
}

【讨论】:

  • 我确实尝试过,但它在 SingleOrDefault() 部分失败,因为结果不止一个用户。我认为当我在一个查询中加载多个集合时结果将是笛卡尔积。想象一下,一个用户有 2 个资源,每个用户都有……比如说 5 个版本……这个场景的结果是(没有单个或默认)10 个用户,每个用户都有资源延迟初始化异常……更不用说版本...
  • 对不起。忘记设置变压器,固定
  • 好的,所以我用 distinctRootEntitiy Transformer 尝试了它,它不会选择 user.Resources 这部分在 SQL 查询中没有加入资源和版本的迹象,所以 user.Resources 会引发延迟初始化异常
  • 我再次尝试了自己,但我在代码中遗漏了一个 .Left。但是我用 NH 3.3.1 测试了这个,所以它可能已经改变了。如果我再次使用它,我将尝试使用 NH 4.0
猜你喜欢
  • 1970-01-01
  • 2011-04-23
  • 2011-07-28
  • 2011-09-30
  • 1970-01-01
  • 2011-11-22
  • 2015-01-02
  • 1970-01-01
相关资源
最近更新 更多