OK, d'abord mon modèle de domaine simple est de 2 classes avec une relation un-à-plusieurs, une simple relation Parent -> enfant. A « Tweet » a un ou plusieurs « votes », mais chaque vote appartient à un seul Tweets etc.NHibernate - Comment écrire cette requête: Sélectionner les parents et trouver un enfant pour chaque parent qui correspond à une condition
public class Tweet
{
public virtual long Id { get; set; }
public virtual string Username { get; set; }
public virtual string Message { get; set; }
public virtual ISet<Vote> Votes { get; set; }
}
public class Vote
{
public virtual long Id { get; set; }
public virtual long TwitterUserId { get; set; }
public virtual DateTime VotedDate { get; set; }
public virtual Tweet Tweet { get; set; }
}
Je suis en train d'écrire une requête dans HQL, ICriteria ou NHibernate LINQ, qui sélectionne tous les Tweets , mais aussi ajouter deux colonnes qui Selects:
- un compte du nombre de voix et ...
- Si un utilisateur particulier a voté pour ce tweet, basé sur un TwitterUserId particulier
Avec les deux colonnes supplémentaires, je ne m'attends pas à récupérer l'objet de domaine Tweet, et j'aurais probablement besoin d'exécuter une requête de rapport, c'est OK. Mais j'ai du mal à comprendre comment écrire cette requête.
Je sais comment écrire ceci comme procédure stockée, ou en utilisant LINQ 2 SQL. Si cela aide, je vais exprimer cela comme une requête LINQ to SQL.
long userId = 123;
var tweets = from t in dataContext.Tweets
where t.Application == app
orderby t.PostedDate desc
select new TweetReport()
{
Id = t.Id,
Username = t.Username,
Message = t.Message,
TotalVotes = t.Votes.Count(),
HasVoted = t.Votes.Any(v => v.TwitterUserId == userId)
};
Je sais que cela fonctionne dans LINQ 2 SQL et générer des T-SQL raisonnablement efficace, mais je ne peux pas comprendre comment écrire ceci dans NHibernate.
Mise à jour: J'ai essayé d'exécuter la requête de LINQ ci-dessus dans NHibernate en utilisant le NHibernate LINQ provider built for NHibernate v2, par exemple:
var tweets = from t in Session.Linq<Tweet>()
where (snip)
Mais cela n'a pas fonctionné. Le support de LINQ dans Nhibernate 3.0 s'est-il amélioré? Je suis un peu réticent à utiliser la version 3.0 parce que c'est toujours alpha, mais si cela fonctionne, alors je pourrais essayer.
Mise à jour 2: Merci à la suggestion de Diego Mijelshon, je suis passé à NHibernate 3.0 alpha 2 et écrit la requête dans LINQ:
var tweets = from t in Session.Query<Tweet>()
where t.App == app
orderby t.PostedDate descending
select t;
int totalRecords = tweets.Count();
var pagedTweets = (from t in tweets
select new TweetReport()
{
Id = t.Id,
TwitterId = t.TweetId,
Username = t.Username,
ProfileImageUrl = t.ImageUrl,
Message = t.Message,
DatePosted = t.PostedDate,
DeviceName = t.Device.Name,
DeviceUrl = t.Device.Url,
TotalVotes = t.Votes.Count(),
HasVoted = t.Votes.Any(v => v.TwitterUserId == userId)
})
.Skip(startIndex)
.Take(recordsPerPage)
.ToList();
return new PagedList<TweetReport>(pagedTweets,
recordsPerPage, pageNumber, totalRecords);
J'ai essayé d'exécuter ceci avec l'ancien fournisseur NHibernate LINQ (celui qui fonctionne avec NHibernate v2) et cela n'a pas fonctionné, lancer une exception. J'ai fait quelques recherches, le fournisseur LINQ de NHibernate a quelques limitations et ne supporte pas les choses comme les sous-sélections. Je le prends LINQ à NHibernate v3 est considérablement amélioré? –
Oui, le nouveau fournisseur intégré prend en charge beaucoup plus de scénarios. J'ai spécifiquement testé votre requête ci-dessus, et cela fonctionne. –
Génial, cela a fonctionné avec brio, merci! –