Pregunta

Tengo una aplicación NHibernate que actualmente utiliza una función definida por el usuario de SQL Server. Me gustaría evitar tener que llamar a esta función y, en su lugar, expresar su lógica utilizando la API de criterios NH. Desafortunadamente, estoy teniendo dificultades para aplicar los ejemplos de criterios en la documentación de NH a mi caso particular. Así que recurro a este sitio en busca de ayuda.

Aquí está la función. Toma un solo argumento de cadena y devuelve una tabla. La función realiza 3 uniones entre las mismas 2 tablas pero con diferentes criterios de unión, y luego fusiona el resultado.

Cualquier sugerencia sería apreciada. Gracias de antemano!

Editar: Esto está dirigido a NH 2.1

Editar: un comentario en la respuesta aceptada indica que la conversión no es posible, que es la respuesta correcta .

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
);

Aquí está el mapeo de las 3 clases involucradas:

<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>
¿Fue útil?

Solución

esto podría hacer el trabajo (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"));

tenga en cuenta, sin embargo, que esto no genera la unión de sintaxis ANSI, sino que coloca las restricciones en una cláusula WHERE. Realmente no creo que sea un problema, estás haciendo una unión interna y no externa.

Además, no recuerdo ahora la notación de parámetro adecuada en Expression.Sql . Lo he definido como : LangId aunque también puede ser @LangId

nota al margen: como puede ver, aunque esta es una consulta de criterios, es solo un montón de sentencias sql divididas para ajustarse a la API de criterios; ¿estás seguro de que esto es lo que necesitas?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top