2015-02-09 6 views
0

позволяет сказать, что у меня есть эта база данных схемаNhibernate Queryover модель многоуровневого

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

и я хочу, чтобы выбрать это с помощью NHibernate в одной базе данных туда и обратно для пользователя по имени пользователя, но выбрать resourceVersions с будущей Безразлично работой. Как увлажнить коллекцию коллекций в одном кругообороте с использованием фьючерсов? Я предпочитаю QueryOver или Criteria over 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> 
... 

только запрос, выполняемые в соответствии с Intelli следа в визуальной студии это одна:

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 является именем пользователя я перейти к метод. Никаких признаков версий, которые я считаю немного странными.

+0

Что не работает? –

+0

Он просто не запрашивает DB для любого запроса, который содержит версии. Кроме того, коллекция версий на ресурсе бросает ленивое исключение инициализации. – LightCZ

+0

Можете ли вы показать свои файлы сопоставления? – Najera

ответ

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(); 
    } 
} 
+0

Я пробовал это, но он не работает на этой части SingleOrDefault(), потому что результат больше, чем один пользователь. Я думал, что результатом будет декартивный продукт, когда я загружаю несколько коллекций по одному запросу. Представьте, что у одного пользователя есть 2 ресурса, и каждый из них имеет ... позволяет сказать 5 версий ... Результат из этого сценария (без единого или по умолчанию) 10 пользователей, у каждого из которых есть ресурсы, версии ... – LightCZ

+0

ах извините. забыл установить трансформатор, исправлено – Firo

+0

Хорошо, поэтому я попробовал его с отличным RootEntitiy Transformer, он не будет выбирать пользователя. Восстанавливает эту часть в SQL-запросе, нет признаков присоединения к ресурсам и версиям, поэтому user.Resources бросает Lazy exception exception – LightCZ

Смежные вопросы