Comment obtenir un résultat distinct avec les API nHibernate et QueryOver?

J’ai cette méthode de repository

public IList ListMessagesBy(ssortingng text, IList tags, int pageIndex, out int count, out int pageSize) { pageSize = 10; var likeSsortingng = ssortingng.Format("%{0}%", text); var query = session.QueryOver() .Where(Ressortingctions.On(m => m.Text).IsLike(likeSsortingng) || Ressortingctions.On(m => m.Fullname).IsLike(likeSsortingng)); if (tags.Count > 0) { var tagIds = tags.Select(t => t.Id).ToList(); query .JoinQueryOver(m => m.Tags) .WhereRessortingctionOn(t => t.Id).IsInG(tagIds); } count = 0; if(pageIndex < 0) { count = query.ToRowCountQuery().FutureValue().Value; pageIndex = 0; } return query.OrderBy(m => m.Created).Desc.Skip(pageIndex * pageSize).Take(pageSize).List(); } 

Vous fournissez une chaîne de recherche de texte libre et une liste de balises. Le problème est que si un message a plus d’une étiquette, il est répertorié des temps dupliqués. Je veux un résultat distinct basé sur l’entité Message. J’ai regardé

 Projections.Distinct 

Mais il nécessite une liste de propriétés pour la question distincte. Ce message est-il la racine de mon entité pour obtenir ce comportement sans fournir toutes les propriétés de l’entité?

Merci d’avance, Anders

    Si vous utilisez l’API ICriteria, vous avez besoin de:

     .SetResultTransformer(new DistinctEntityRootTransformer()) 

    Si vous utilisez l’API QueryOver, vous avez besoin de:

     .TransformUsing(Transformers.DistinctRootEntity) 

    Mais méfiez-vous, tout cela se passe côté client, donc toutes les lignes en double sont toujours tirées.

    Essayez quelque chose comme ça

     public IPagedList Find(int pageIndex, int pageSize) { Client clientAlias = null; var query = Session.QueryOver(() => clientAlias) .Select( Projections.Distinct( Projections.ProjectionList() .Add(Projections.Property(x => x.Id).As("Id")) .Add(Projections.Property(x => x.Name).As("Name")) .Add(Projections.Property(x => x.Surname).As("Surname")) .Add(Projections.Property(x => x.GivenName).As("GivenName")) .Add(Projections.Property(x => x.EmailAddress).As("EmailAddress")) .Add(Projections.Property(x => x.MobilePhone).As("MobilePhone")) ) ) .TransformUsing(Transformers.AliasToBean()) .OrderBy(() => clientAlias.Surname).Asc .ThenBy(() => clientAlias.GivenName).Asc; var count = query .ToRowCountQuery() .FutureValue(); return query .Take(pageSize) .Skip(Pagination.FirstResult(pageIndex, pageSize)) .List() .ToPagedList(pageIndex, pageSize, count.Value); } 

    Vous pouvez utiliser SelectList et GroupBy, par exemple:

     tags.SelectList(t => t.SelectGroup(x => x.Id)) 

    Devrait fonctionner et produire le même plan de requête que distinct.

    Si vous avez besoin de plusieurs éléments dans le groupe, faites comme:

     tags.SelectList(t => t.SelectGroup(x => x.Id) .SelectGroup(x => x.Name) ) 

    J’ai récemment créé une méthode pour appliquer select distinct en fonction d’un type d’object mappé. Cela s’applique à un object IQueryOver (propriété de la classe). La méthode a également access à la configuration nhibernate. Vous pouvez les append comme parameters de méthode. Besoin de travail pour la production, mais la méthode fonctionne très bien en dev, elle ne l’a utilisée que pour une seule entité jusqu’à présent.

    Cette méthode a été créée car j’essaie de mettre en page mes données au niveau du serveur et un transformateur de résultat distinct ne fonctionnerait pas.

    Une fois que vous avez obtenu votre collection d’objects (query.List ()), vous devrez peut-être recharger les objects pour remplir un à plusieurs objects enfants. Un grand nombre de mappages seront envoyés par proxy pour les charges paresseuses.

      public void DistinctRootProjectionList() { var classMapping = Context.Config.GetClassMapping(typeof(E)); var propertyIterator = classMapping.UnjoinedPropertyIterator; List projections = new List(); ProjectionList list = Projections.ProjectionList(); list.Add(Projections.Property(classMapping.IdentifierProperty.Name), classMapping.IdentifierProperty.Name); foreach (var item in propertyIterator) { if (item.Value.IsSimpleValue || item.Value.Type.IsEntityType) { list.Add(Projections.Property(item.Name), item.Name); } } query.UnderlyingCriteria.SetProjection(Projections.Distinct(list)); query.TransformUsing(Transformers.AliasToBean()); } 

    Code que j’ai utilisé pour charger une à plusieurs relations … T est le type d’entité.

     for (int i = 0; i < resp.Data.Count; i++) { resp.Data[i] = session.Load(GetInstanceIdValue(resp.Data[i])); }