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
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?
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.
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()
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.
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());
}
};
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.
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()));
};
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.