2009-03-04 6 views
1

Je souhaite exécuter une requête sur deux tables (qui sont mappées dans ActiveRecord). La requête renvoie une liste de résultats qui ne peut pas être mappée à un objet ActiveRecord (car il s'agit d'informations agrégées personnalisées).Comment exécuter une requête HqlBasedQuery qui renvoie une liste non mappée d'objets à l'aide de nHibernate?

Par exemple

Dim query_str en tant que chaîne = "Sélectionner d.ID distincte, (select count (1) exp de Sales_Leads où DATE_CREATED < =: todays_date) comme NbrLeads de revendeur d"

Dim q Comme Queries.HqlBasedQuery = New Queries.HqlBasedQuery (GetType (ICollection), query_str) q.SetParameter ("todays_date", DateTime.Today) Dim i Comme ICollection = ActiveRecordMediator.ExecuteQuery (q)

Qu'est-ce que je Je cherche est une simple exécution de SQL, sans Objet ActiveRecord renvoyé. Donc, idéalement, je serais capable de regarder i ("NbrResults") pour chaque élément de la collection.

L'erreur que je reçois est:

Vous avez accédé à une classe ActiveRecord qui n'a pas été correctement initialisé . La seule explication est que l'appel à ActiveRecordStarter.Initialize() ne comprenait pas System.Collections.ICollection classe

Répondre

0

Voici ma solution finale était:

Dim query_str As String = « SELECT DISTINCT d.ID, compte (l) de LEAD comme l rejoindre l.Dealer comme d où l.DateCreated> = DATEADD (jour, -30,: todays_date) GROUP BY d.ID "

Puis obtenir le dossier actif session (ou NHibernate, ne sait toujours pas ce qui est retourné ici):

Dim sess Comme ISession = activerecordmediator.GetSessionFactoryHolder(). CreateSession (GetType (ActiveRecordBase))

Dim q Comme NHibernate.IQuery = sess.CreateQuery (query_str)

q.SetParameter ("todays_date" , DateTime.Today) Dim i comme IList = q.List() 'obtenir des résultats

dans la page .aspx, le résultat peut être consulté dans un GridView comme ceci:

0

Yo Nous sortons du paradigme de NHibernate pour faire appel à SQL, ce qui va un peu à l'encontre de l'esprit d'ORM. Ce n'est pas «mauvais» en soi, mais j'éviterais certainement de rompre l'abstraction si je pouvais essayer de maintenir un couplage plus lâche.

Vous pouvez faire ce que vous voulez avec une requête HQL droite, qui retournera une collection de tuples contenant les résultats de votre requête. Je lui ai expliqué comment faire ici

Custom query with Castle ActiveRecord

que vous pouvez jeter un oeil à.Même si vous devez spécifier un type lorsque vous créez un HQLBasedQuery, NH est assez intelligent pour savoir que si vous ne sélectionnez pas une instance de type, il doit assembler un ensemble de résultats basé sur les tuples d'objet. (IMNSHO c'est encore un peu non pur - je serais tenté d'essayer de modéliser cette relation comme un objet et de la mapper en conséquence, mais ensuite je devrais mettre la base de données en forme pour l'adapter au modèle de l'objet et ça ne va pas voler dans tous les cas.)

2

Eh bien, cela a été demandé il y a longtemps, mais j'ai une réponse de travail.

public static IList<T> ExecuteQuery<T>(HqlBasedQuery query) 
    where T : new() 
{ 
    query.SetResultTransformer(new NHibernate.Transform.AliasToBeanResultTransformer(typeof(T))); 
     var results = (ArrayList)ActiveRecordMediator.ExecuteQuery(query); 

    List<T> list = new List<T>(results.Count); 
    for (int i = 0; i < results.Count; i++) 
    { 
     list.Add((T)results[i]); 
    } 

    return list; 
} 

Cela vous donnera de retour des résultats de type de type T. T peut être quoi que ce soit que vous voulez. Le type T nécessite un constructeur sans argument et nécessite des champs publics ou des propriétés correspondant aux noms de colonnes ou aux alias dans la requête que vous créez.

Nous faisons cela tout le temps. Particulièrement lorsque vous voulez utiliser la fonction d'agrégation dans HQL pour produire des données agrégées.

Une fonction d'accompagnement vous permettra de passer simplement dans votre requête comme une chaîne, ainsi que tous les paramètres de position que vous pourriez avoir:

public static IList<T> ExecuteQuery<T, U>(string hqlQuery, params object[] parameters) 
     where T : new() 
    { 
     return ExecuteQuery<T>(new HqlBasedQuery(typeof(U), hqlQuery, parameters)); 
    } 

Type U est tout type qui est un type ActiveRecord valide. Il ne doit même pas être l'un des types auxquels vous faites référence. Si vous voulez, vous pouvez le remplacer par un type dont vous savez qu'il va être valide dans la session et abandonner le paramètre supplémentaire.

Questions connexes