Pergunta

Eu tenho um aplicativo NHibernate que atualmente faz uso de uma função definida pelo usuário SQL Server. Eu gostaria de evitar ter que chamar esta função e, em vez expressar sua lógica usando o NH critérios API. Infelizmente, eu estou tendo dificuldade em aplicar os exemplos de critérios na documentação NH para o meu caso particular. Então, eu estou voltando para este site para obter ajuda.

Aqui é a função. Leva um único argumento de cadeia e retorna uma tabela. A função executa 3 junções entre os mesmos 2 mesas, mas com diferentes critérios de união, e depois funde-se o resultado.

Alguma dica seria apreciada. Agradecemos antecipadamente!

Editar: Esta é a segmentação NH 2.1

Editar:. Um comentário nos estados resposta aceita que a conversão não é possível, que é a correta resposta

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

Aqui está o mapeamento para as 3 classes envolvidas:

<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>
Foi útil?

Solução

isso pode fazer o trabalho (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"));

nota, porém, que esta não gera ANSI sintaxe participar, mas coloca as restrições em uma cláusula WHERE. Eu realmente não acho que isso é um problema, você está fazendo uma junção interna e não uma associação externa.

Também eu não me lembro agora a notação parâmetro adequado na Expression.Sql. Eu defini-lo como :LangId embora também possa ser @LangId

sidenote: como você pode ver, embora este é um critério de consulta é apenas um monte de SQL-indicações divididas, de modo que se encaixam no critério API; você tem certeza que é isso que você precisa?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top