Besoin d'aide pour convertir SQL en API de critères
-
08-07-2019 - |
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>
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?