Domanda

Sto cercando di mappare l'output di una stored procedure per un oggetto nel mio progetto utilizzando NHibernate.

L'oggetto viene delcared in questo modo:

public class NewContentSearchResult
{
    public string Name { get; set; }
    public string ContentType { get; set; }
    public int Count { get; set; }
    public int CMIId { get; set; }
    public int FeatureId { get; set; }

    public override bool Equals(object obj)
    {
        return base.Equals(obj);
    }

    public override int GetHashCode()
    {
        return base.GetHashCode();
    }
}

e la mappatura si presenta così:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="Class.Assembly"
    namespace="Class.Assembly"
    default-lazy="false" default-cascade="none">
  <class name="NewContentSearchResult" mutable="false" check="none">
    <composite-id unsaved-value="none">
      <key-property name="CMIId" type="int" />
      <key-property name="FeatureId" type="int" />
    </composite-id>
    <property name="ContentType" type="string" />
    <property name="Name" type="string" />
    <property name="Count" type="int" />
  </class>
  <sql-query name="spWebGetNewContentBySalesRole">
    <return class="NewContentSearchResult" lock-mode="read">
      <return-property name="Name" column="Name" />
      <return-property name="ContentType" column="FeatureDesc" />
      <return-property name="Count" column="Number" />
      <return-property name="CMIId" column="CMIId" />
      <return-property name="FeatureId" column="FeatureId" />
    </return>
    exec core.spWebGetNewContentBySalesRole :SalesRoleId
  </sql-query>
</hibernate-mapping>

La chiamata di stored procedure è corretta, e io tornare risultati che assomigliano a questo per SalesRoleId 266 (come esempio):

CMIId       FeatureDesc       FeatureId     Name       Count
4000719 Guest Book          12     Charlie Brown    2
4000719 Audio Guest Book    3      Charlie Brown    1

Senza la chiave composta (utilizzando solo il CMIId) funziona bene, tranne quando ci sono 2 risultati (come sopra) che condividono un CMIId ... il 2 ° viene sovrascritto dal primo.

devo usare una chiave composta, e CMIId / FeatureId è la combinazione logica.

Quando eseguo questo ora, ottengo un'eccezione:

NHibernate.ADOException: could not execute query
[ exec core.spWebGetNewContentBySalesRole ? ]
  Name: SalesRoleId - Value: 266
[SQL: exec core.spWebGetNewContentBySalesRole ?] --->  System.IndexOutOfRangeException: CMIId22_0_.
È stato utile?

Soluzione

Ok, ulteriori ricerche mi ha convinto che non è possibile avere gli ID composite in NHibernate quando si utilizza una stored procedure.

A tal fine, ho modificato il mio SQL per includere RowNumber () e sto usando che come un id. Posso solo fare questo perché è di sola lettura, senza scritte al db, ma funziona per il mio scopo.

Altri suggerimenti

In passato, quando ho usato un composito-chiave che ho sempre avuto per creare una classe separata per tale ID con le proprietà della classe corrispondenti ai tasti separati per il composito. Hai provato questo?

Come accennato nella risposta accettato, ho finito per usare un unico numero di riga mod in Oracle utilizzando la funzione ROWNUM. Più tardi, mi sono imbattuto in un problema quando si riutilizza la query con parametri diversi. Sembra che NHibernate ricordato gli ID e voleva associarli con i risultati di recente restituiti, portando così indietro le righe non corrette. Ho fissato questo combinando il numero di riga con un timestamp così:

(ROWNUM * 10000000000 + dbms_utility.get_time) AS ROW_ID

In questo modo avrete la garanzia di ottenere completamente nuovi ID per i risultati della query ogni volta. Basta fare in modo di utilizzare un grande numero intero sufficiente a contenere il valore nell'oggetto mappato. Io uso un ulong in C # .NET, che è di 8 byte. Si può anche prendere un paio di 0s fuori del moltiplicatore per rendere l'ID più breve.

Un po 'tardi nel corso della giornata, ma posso seconda Mark Struzinski -. Questo è possibile

ho funzionato in questo problema di recente e risolto utilizzando una classe separata per la chiave composito e utilizzando elementi all'interno della mappatura come segue.

<sql-query name="spWebGetNewContentBySalesRole" >
    <return class="NewContentSearchResult">
        <return-property name="NewContentSearchResultKey">
            <return-column name="CMIIdColumn" />
            <return-column name="FeatureIdColumn" />
        </return-property>
        <return-property name="Name" column="Name" />       
        <return-property name="ContentType" column="FeatureDesc" />       
        <return-property name="Count" column="Number" />       
    </return>
    exec core.spWebGetNewContentBySalesRole :SalesRoleId 
</sql-query>

Si noti che il "nome" attributi all'interno degli elementi di ritorno colonne rappresentano i nomi nel set di risultati, e dovrebbe essere nello stesso ordine in cui le proprietà della classe id.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top