3 votes

Chargement rapide d'entités liées à partir d'une fonction à valeur de tableau dans NHibernate

J'ai donc une fonction à valeur de tableau dans ma dabatase qui effectue une requête lourde et complexe basée sur plusieurs paramètres, et renvoie par exemple trois colonnes : OrderId , SomeCalc1 , SomeCalc2 .

Maintenant, pour traduire cela dans NHibernate, la seule solution que j'ai trouvée est d'utiliser des requêtes nommées. Mon mapping est le suivant :

<class name="OrderWithSomeExtraInfo">
  <id name="OrderId" column="OrderId"/>
  <many-to-one name="Order" update="false" insert="false">
    <column name="OrderId"/>
  </many-to-one>
  <property name="SomeCalc1" column="SomeCalc1" update="false" insert="false"/>
  <property name="SomeCalc2" column="SomeCalc2" update="false" insert="false"/>
</class>

<sql-query name="GetOrdersWithSomeCalc">
 <return class='MyDomain.OrderWithSomeExtraInfo, MyDomain' alias='o'/>

 <![CDATA[

  SELECT F.SomeCalc1 AS {o.SomeCalc1}, F.SomeCalc2 AS {o.SomeCalc2}, F.OrderId AS {o.OrderId}
  FROM [dbo].[funcSomething] ( :Param1, :Param2, :StartDate, :EndDate ) AS F

 ]]>
</sql-query>

Et ensuite, dans le code, j'appelle avec ce qui suit :

 IEnumerable<OrderWithSomeExtraInfo> query =
         Session.GetNamedQuery("GetOrdersWithSomeCalc")
         .SetString("Param1", p1)
         .SetString("Param2", p2)
         .SetDateTime("StartDate", StartDate)
         .SetDateTime("EndDate", EndDate)
         .Future<OrderWithSomeExtraInfo>();

Et ce que je voudrais faire, c'est que, dans le code, je sois impatient de récupérer également les Order de OrderWithSomeExtraInfo, et aussi quelques many-to-ones chaînés. Quelque chose comme ça :

  IEnumerable<OrderWithSomeExtraInfo> query =
         Session.GetNamedQuery("GetOrdersWithSomeCalc")
         .SetString("Param1", p1)
         .SetString("Param2", p2)
         .SetDateTime("StartDate", StartDate)
         .SetDateTime("EndDate", EndDate)
         .Fetch(owse => owse.Order)
         .ThenFetch(o => o.Customer)
         .Future<OrderWithSomeExtraInfo>();

Cependant, je ne trouve pas le moyen de le faire, car il ne s'agit pas d'une requête NHibernate LINQ. Je ne sais donc pas comment eager fetch lorsque l'origine est une requête SQL native, ni comment mapper une fonction à l'API LINQ ou QueryOver.

0voto

silverfighter Points 2607

Tout d'abord, je dois m'excuser, car je ne connais pas grand-chose à NHibernate, mais comme personne n'a encore répondu, je vais faire de mon mieux pour partager quelques informations que j'ai trouvées.

Voici un très bon article d'Aende, le créateur de NHibernate. Il explique comment utiliser les procédures stockées avec du SQL personnalisé et des entités qui vivent dans une relation. https://ayende.com/blog/1692/using-nhibernate-with-stored-procedures

Il semble que si vous voulez l'association entre la commande et le client (<- c'est ce que j'ai compris) alors vous devez aussi la modéliser (ou la mapper dans votre xml).

Au milieu de l'article, il y a la chose que vous cherchez peut-être. Voici quelque chose comme <loader query-ref="allSalariesForEmployee"/> dans l'article qui devrait être responsable de l'association. Cela devrait également être possible si l'associé ne provient pas d'une procédure stockée.

J'espère que cela vous aidera et que j'ai bien compris votre question.

0voto

TwistedStem Points 250

Essayez de changer votre requête nommée en quelque chose comme ceci :

  <sql-query name="GetOrdersWithSomeCalc">
    <![CDATA[
      SELECT *
      FROM [dbo].[funcSomething] (:Param1,:Param2,:StartDate,:EndDate ) as F
      JOIN [dbo].[Orders] O ON F.OrderId = O.OrderId
      JOIN [dbo].[Customers] C ON O.CustomerId = C.CustomerId
     ]]>
    <return alias='f' class='MyDomain.OrderWithSomeExtraInfo, MyDomain'/>
    <return-join alias='o' property='f.Order' />
    <return-join alias='c' property='o.Customer' />
  </sql-query>

Cela devrait ' avec impatience remplir votre objet (en utilisant votre premier exemple, pas besoin des instructions .Fetch ou .FetchNext) . J'ai extrapolé les noms des tables et des colonnes Id ; vous devrez peut-être les modifier en fonction de votre convention de dénomination.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X