Question

Je possède une application NHibernate qui utilise actuellement une fonction définie par l'utilisateur SQL Server. Je souhaite éviter d’appeler cette fonction et d’exprimer sa logique à l’aide de l’API des critères NH. Malheureusement, j'ai du mal à appliquer les exemples de critères de la documentation NH à mon cas particulier. Je me tourne donc vers ce site pour obtenir de l'aide.

Voici la fonction. Il faut un seul argument de chaîne et retourne une table. La fonction effectue 3 jointures entre les mêmes 2 tables mais avec des critères de jointure différents, puis fusionne le résultat.

Toute suggestion serait la bienvenue. Merci d'avance!

Modifier: ceci cible NH 2.1

Modifier: Un commentaire dans la réponse acceptée indique que la conversion est impossible, ce qui correspond à la réponse correcte .

CREATE FUNCTION dbo.GetRevisionText
(
  @LangId NVARCHAR(16)
)
RETURNS TABLE
AS
RETURN
(
  SELECT r.RevisionId,
    COALESCE(lp1.Title, lp2.Title, lp3.Title) Title,
    COALESCE(lp1.Description, lp2.Description, lp3.Description) Description
    FROM Revision r
      LEFT JOIN LocalizedProperty lp1
        ON lp1.RevisionId = r.RevisionId
        AND lp1.LanguageId = @LangId
      LEFT JOIN LocalizedProperty lp2
        ON lp2.RevisionId = r.RevisionId
        AND lp2.LanguageId = LEFT(@LangId, 2)
      LEFT JOIN LocalizedProperty lp3
        ON lp3.RevisionId = r.RevisionId
        AND lp3.LanguageId = r.DefaultPropertiesLanguage
);

Voici le mappage pour les 3 classes impliquées:

<class name="Revision">
  <id name="RevisionId" type="Guid">
    <generator class="assigned"/>
  </id>
  <set name="LocalizedProperties" inverse="true" lazy="true" cascade="all-delete-orphan">
    <key column="RevisionId"/>
    <one-to-many class="LocalizedProperty"/>
  </set>
  <many-to-one name="DefaultPropertiesLanguage" class="Language" not-null="true"/>
</class>

<class name="Language">
  <id name="LanguageId" type="String" length="16">
    <generator class="assigned"/>
  </id>
  <property name="Lcid" type="Int32" unique="true" not-null="true"/>
</class>

<class name="LocalizedProperty" mutable="false">
  <composite-id>
    <key-many-to-one name="Revision" class="Revision" column="RevisionId"/>
    <key-many-to-one name="Language" class="Language" column="LanguageId"/>
  </composite-id>
  <property name="Title" type="String" length="200" not-null="true"/>
  <property name="Description" type="String" length="1500" not-null="false"/>
</class>
Était-ce utile?

La solution

cela pourrait faire le travail (NH 1.2):

var crit = nhSes.CreateCriteria(typeof(Revision), "r")
 .SetProjection(
  Projections.SqlProjection(@"r.RevisionId as rid,
    COALESCE(lp1.Title, lp2.Title, lp3.Title) as Title,
    COALESCE(lp1.Description, lp2.Description, lp3.Description) as Description", new[] {"rid", "Title", "Description"}, new[] {NHibernateUtil.Guid, NHibernateUtil.String,NHibernateUtil.String})
 );

crit.CreateCriteria("LocalizedProperty", "lp1", JoinType.InnerJoin);
crit.CreateCriteria("LocalizedProperty", "lp2", JoinType.InnerJoin);
crit.CreateCriteria("LocalizedProperty", "lp3", JoinType.InnerJoin);

crit.Add(Expression.Eq("lp1.LanguageId", langId));
crit.Add(Expression.Sql("lp2.LanguageId = LEFT(:LangId, 2)", langId, NHibernateUtil.String));
crit.Add(Expression.EqProperty("lp3.LanguageId", "r.DefaultPropertiesLanguage"));

notez cependant que cela ne génère pas de jointure de syntaxe ANSI, mais place les contraintes dans une clause WHERE. Je ne pense pas vraiment que ce soit un problème, vous faites une jointure interne et non une jointure externe.

De plus, je ne me souviens plus de la notation de paramètre appropriée dans Expression.Sql . Je l'ai défini comme : LangId , bien qu'il puisse également s'agir de @LangId

sidenote: comme vous pouvez le constater, il s'agit d'une requête de critères. Elle consiste simplement en un groupe d'instructions SQL divisées de manière à correspondre à l'API des critères. êtes-vous sûr que c'est ce dont vous avez besoin?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top