This is a migrated thread and some comments may be shown as answers.

aggregation on functions against client-side data

8 Answers 121 Views
GridView
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Aaron
Top achievements
Rank 1
Aaron asked on 14 Sep 2012, 06:06 PM
I've got a paged gridview bound to an itemssource of QueryableDomainServiceCollectionView. The gridview  allows the user to group, sort, and filter data. Problem is I'm getting an aggregate of something like count: 10 on a particular group that may have 300 entries. The count of 10 comes from the data that happens to be on that page.

The aggregate is operating against the client-side data which doesn't portray the actual values. I want it to query the server. Since I'm using the QueryableDomainServiceCollectionView I would expect it to do so. 

Is there any solution to this?

8 Answers, 1 is accepted

Sort by
0
Aaron
Top achievements
Rank 1
answered on 14 Sep 2012, 06:37 PM
I just re-read this and realized it wasn't clear at all. I've edited my original post.
0
Dimitrina
Telerik team
answered on 17 Sep 2012, 07:41 AM
Hi,

Please keep in mind that when the GridView is being paged, it is actually aware of the current page only. As I understand you have defined aggregate function on the GridView, is that correct? May I ask you to share how have you bound the GridView to a QueryableDomainServiceCollectionView source?
 

Greetings,
Didie
the Telerik team

Time to cast your vote for Telerik! Tell DevPro Connections and Windows IT Pro why Telerik is your choice. Telerik is nominated in a total of 25 categories.

0
Aaron
Top achievements
Rank 1
answered on 17 Sep 2012, 04:34 PM
view:
<
telerik:RadGridView ItemsSource="{Binding DataSource}" />

viewmodel:
public QueryableDomainServiceCollectionView<TEntity> DataSource
{
    get
    {
        return this.dataSource;
    }
 
    protected set
    {
        if (value != dataSource)
        {
            dataSource = value;
            RaisePropertyChanged("DataSource");
        }
    }
}


Initializing datasource within the viewmodel:
QueryableDomainServiceCollectionView<TEntity> newDataSource = new QueryableDomainServiceCollectionView<TEntity>(context, query);
newDataSource.AutoLoad = true;
newDataSource.PageSize = pageSize;
newDataSource.LoadedData += new EventHandler<Telerik.Windows.Controls.DomainServices.LoadedDataEventArgs>(OnReportDataSourceLoadedData);
newDataSource.LoadingData += new EventHandler<Telerik.Windows.Controls.DomainServices.LoadingDataEventArgs>(OnReportDataSourceLoadingData);
newDataSource.SubmittingChanges += new EventHandler<Telerik.Windows.Controls.DomainServices.DomainServiceSubmittingChangesEventArgs>(OnSubmittingChanges);
newDataSource.SubmittedChanges += new EventHandler<Telerik.Windows.Controls.DomainServices.DomainServiceSubmittedChangesEventArgs>(OnSubmittedChanges);
DataSource = newDataSource;

The context in this case is my DomainContext and query is my EntityQuery. I'm later adding within the "AutoGeneratingColumn" event:
e.Column.AggregateFunctions.Add(new CountFunction()


0
Rossen Hristov
Telerik team
answered on 18 Sep 2012, 10:55 AM
Hi,

Aggregates cannot be calculated over the entire array of server data in case you have paging. When there is paging, RadGridView can not be aware of anything else besides the data that it currently shows. When there is paging, Skip and Take is appended to the query. The data comes back and is filled inside the QDSCV. RadGridView is bound to this QDSCV and only "knows" about this data that came to the client. It cannot do an aggregate over the entire data residing on the server. It does not really know where and how data is coming from.

I hope this makes sense.

Regards,
Ross
the Telerik team

Time to cast your vote for Telerik! Tell DevPro Connections and Windows IT Pro why Telerik is your choice. Telerik is nominated in a total of 25 categories.

0
Aaron
Top achievements
Rank 1
answered on 28 Sep 2012, 01:13 AM
Except the QDSCV has access to the server, and can easily ask...This code will take an arbitrary column name from the group descriptor and return the aggregates over the entire data source:


LoadOperation<MyClass> myOp = myQDSCV.DomainContext.Load(myQDSCV.EntityQuery);
myOp.Completed += (sender, args) =>
    {
        // Create a "GroupBy" expression for an arbitrary column
        ParameterExpression columnParam = Expression.Parameter(typeof(MyClass), "column");
        Expression<Func<MyClass, string>> groupSelector = Expression.Lambda<Func<MyClass, string>>(
            Expression.Property(columnParam, myGroupDescriptor.Member),
            columnParam
        );
 
        // Query for the group aggregate, only need to get count, sum, or average based upon the aggregate
        //    but for demonstration purposes I'm getting all...
        var qry = from stat in myOp.Entities.GroupBy(groupSelector.Compile())
                  select new
                  {
                      Key = stat.Key,
                      Count = stat.Count(),
                      Average = stat.Average(),
                      Sum = stat.Sum()
                  };
 
        // Do something with the data, ideally populating "AggregateResults"
        List<Tuple<string, string>> test = new List<Tuple<string, string>>();
        foreach (var stat in qry)
        {
            test.Add(new Tuple<string, string>(stat.Key, stat.Count.ToString()));
        }
 
        // Test output
        foreach (Tuple<string, string> aggregate in test)
        {
            System.Diagnostics.Debug.WriteLine(aggregate.ToString());
        }
    };

0
Rossen Hristov
Telerik team
answered on 28 Sep 2012, 07:12 AM
Hello,

The EntityQuery class does not support the GroupBy LINQ query operator. So to aggregate over the entire set of server data, this entire set of server data has to be pulled back to the client. Which in turn makes paging totally useless, since all of the data will be brought back to the client anyway.

I am afraid that we cannot easily implement this functionality that you require.

Your best option would be to manually pull all data to the client (DomainContext.Load), fill it up in an in-memory collection, i.e. ObservableCollection<T> and then bind the grid to this collection. You can disable paging, since it will be client-side anyway. Then each group should show the aggregate result over the entire set of data.

Kind regards,
Ross
the Telerik team

Time to cast your vote for Telerik! Tell DevPro Connections and Windows IT Pro why Telerik is your choice. Telerik is nominated in a total of 25 categories.

0
Aaron
Top achievements
Rank 1
answered on 28 Sep 2012, 07:10 PM
Count can be pulled back without pulling all data using a where and take(0) combined with IncludeTotalCount like the following code. Regardless though I think I get why this can't be a broad-spectrum solution. I, however, need this functionality. Are there any suggestions for actually using this or something similar to populate my aggregates?

ParameterExpression item = Expression.Parameter(typeof(myClass), "item");
MemberExpression prop = Expression.Property(item, myColumnName);
ConstantExpression soap = Expression.Constant(myGroupedValue);
BinaryExpression equal = Expression.Equal(prop, soap);
Expression<Func<myClass, bool>> lambda = Expression.Lambda<Func<myClass, bool>>(equal, item);
 
EntityQuery<myClass> myQuery = DataSource.EntityQuery.Where(lambda).Take(0);
myQuery.IncludeTotalCount = true;
LoadOperation<myClass> myOp = DataSource.DomainContext.Load(myQuery);
myOp.Completed += (sender, args) =>
{
    System.Diagnostics.Debug.WriteLine(string.Format("Total amount in group {0} is {1}", myGroupedValue, myOp.TotalEntityCount.ToString()));
};
0
Rossen Hristov
Telerik team
answered on 01 Oct 2012, 06:00 AM
Hi,

The only workaround for such a functionality would be to create a custom group footer and a custom grid footer and don't rely on the built-in ones. Since it is custom, you will be able to place any user control inside it. You would have to somehow pull the data that you need from the server and display it there.

An online example about custom footers can bee seen here.

All the best,
Ross
the Telerik team

Time to cast your vote for Telerik! Tell DevPro Connections and Windows IT Pro why Telerik is your choice. Telerik is nominated in a total of 25 categories.

Tags
GridView
Asked by
Aaron
Top achievements
Rank 1
Answers by
Aaron
Top achievements
Rank 1
Dimitrina
Telerik team
Rossen Hristov
Telerik team
Share this question
or