How to get a distinct result with nHibernate and QueryOver API?

前端 未结 4 1976
悲&欢浪女
悲&欢浪女 2020-12-25 10:01

I have this Repository method

    public IList ListMessagesBy(string text, IList tags, int pageIndex, out int count, out int pageSi         


        
相关标签:
4条回答
  • 2020-12-25 10:26

    Try something like this

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

    If you're using the ICriteria API, you need:

    .SetResultTransformer(new DistinctEntityRootTransformer())
    

    If you're using the QueryOver API, you need:

    .TransformUsing(Transformers.DistinctRootEntity)
    

    But beware, this all occurs on client side, so all the duplicate rows are still pulled.

    0 讨论(0)
  • 2020-12-25 10:37

    I have recently created a method to apply select distinct based on a mapped object type. It applies this to an IQueryOver object (property of class). Method also has access to the nhibernate config. You could add these as method parameters. Needs work for production, but method is working great in dev, only used it for one entity so far.

    This method was created because I am trying to page my data at the server level and a distinct result transformer would not work.

    After you get your object collection (query.List()) you may have to reload the objects to populate one to many child objects. Many to one mappings will be proxied for lazy loads.

     public void DistinctRootProjectionList<E>()
        {
            var classMapping = Context.Config.GetClassMapping(typeof(E));
            var propertyIterator = classMapping.UnjoinedPropertyIterator;
            List<IProjection> projections = new List<IProjection>();
            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<E>());
        }
    

    Code I used to load one to many relations... T is the entity type.

    for (int i = 0; i < resp.Data.Count; i++)
            {
                resp.Data[i] = session.Load<T>(GetInstanceIdValue(resp.Data[i]));
            }
    
    0 讨论(0)
  • 2020-12-25 10:41

    You can use SelectList and GroupBy, e.g:

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

    Should work and produce the same query plan as distinct.

    If you need multiple items in the group, do something like:

    tags.SelectList(t => t.SelectGroup(x => x.Id)
                          .SelectGroup(x => x.Name)
                   )
    
    0 讨论(0)
提交回复
热议问题