We use the RadGrid extensively throughout our system, and, with simple datasets, it works great, even with a lot of data. However, we have one page with a series of complicated radgrids - lots of data, lots of template columns, lots of eval statements, and a number of custom controls that bind data from an object property. We're experiencing major performance problems with these grids. I added a number of debug statements and it's taking 6-7 or even 10+ seconds to bind the grid (timestamps between the Grid DataBinding and DataBound events). We're already using custom paging, and our page size is 60 records. I'm trying to find ways to improve this performance, and would welcome any suggestions:
- Would it be better to bind to a flat collection of data? That is, rather than passing an object property using eval to a custom control which then pulls out properties of that object, flatten each property in the underlying data item. So instead of 5 AlternateSource objects, flatten it to AlternateSource1DataSource, AlternateSource1Price, AlternateSource2DataSource, AlternateSource2Price, etc. Basically binding to a DataRow rather than a custom object.
- Microsoft says that the Eval Method can slow performance because it reflection at run time (http://msdn.microsoft.com/en-us/library/4hx47hfe(v=vs.110).aspx). Should I use as many GridBoundColumns as I can and bind data in the template columns on the ItemDataBound event, rather than using Eval in the aspx file? This means I would need a bunch of GridBoundColumns set to display hidden to get the data in the event, which is tedious. Or stuff the data into the DataKey collection. It also means I can't do much binding with a sub-object in the itemdatabound event.
- What's the performance impact of putting a lot of data into the DataKey collection? Is there any other way to access to the direct directly in the ItemDataBound event. I'm fairly certain you can't access the underlying data object in the ItemDataBound event. Is that correct?
For reference, here's an example of one of our grids:
- Would it be better to bind to a flat collection of data? That is, rather than passing an object property using eval to a custom control which then pulls out properties of that object, flatten each property in the underlying data item. So instead of 5 AlternateSource objects, flatten it to AlternateSource1DataSource, AlternateSource1Price, AlternateSource2DataSource, AlternateSource2Price, etc. Basically binding to a DataRow rather than a custom object.
- Microsoft says that the Eval Method can slow performance because it reflection at run time (http://msdn.microsoft.com/en-us/library/4hx47hfe(v=vs.110).aspx). Should I use as many GridBoundColumns as I can and bind data in the template columns on the ItemDataBound event, rather than using Eval in the aspx file? This means I would need a bunch of GridBoundColumns set to display hidden to get the data in the event, which is tedious. Or stuff the data into the DataKey collection. It also means I can't do much binding with a sub-object in the itemdatabound event.
- What's the performance impact of putting a lot of data into the DataKey collection? Is there any other way to access to the direct directly in the ItemDataBound event. I'm fairly certain you can't access the underlying data object in the ItemDataBound event. Is that correct?
For reference, here's an example of one of our grids:
<
rad:RadGrid
ID
=
"gridData"
AllowFilteringByColumn
=
"false"
AllowSorting
=
"false"
runat
=
"server"
OnNeedDataSource
=
"GridData_NeedDataSource"
OnItemDataBound
=
"GridData_ItemDataBound"
OnItemCommand
=
"GridData_ItemCommand"
OnUpdateCommand
=
"GridData_ItemUpdated"
OnInit
=
"GridData_PreRender"
>
<
GroupingSettings
CaseSensitive
=
"false"
/>
<
ExportSettings
ExportOnlyData
=
"false"
/>
<
MasterTableView
Name
=
"Exceptions"
EditMode
=
"InPlace"
EnableHeaderContextMenu
=
"true"
DataKeyNames
=
"MurexMkt, PrimaryTicker"
>
<
Columns
>
<
rad:GridTemplateColumn
HeaderText
=
""
ItemStyle-HorizontalAlign
=
"Center"
HeaderStyle-Width
=
"10"
HeaderStyle-Font-Bold
=
"true"
UniqueName
=
"Approve"
AllowFiltering
=
"false"
>
<
HeaderTemplate
>
<
input
type
=
"checkbox"
id
=
"chkAll"
onclick
=
"CheckAll(this);"
/>
</
HeaderTemplate
>
<
ItemTemplate
>
<
asp:CheckBox
ID
=
"chkApprove"
Style
=
"margin-right: -6px;"
runat
=
"server"
CssClass
=
"GridApproveCheckbox"
/>
</
ItemTemplate
>
</
rad:GridTemplateColumn
>
<
rad:GridBoundColumn
DataField
=
"StagePriceExceptionId"
ReadOnly
=
"true"
HeaderText
=
"ExcID"
AllowFiltering
=
"false"
HeaderStyle-Width
=
"40"
Display
=
"false"
/>
<
rad:GridBoundColumn
DataField
=
"StagePriceId"
ReadOnly
=
"true"
HeaderText
=
"ID"
AllowFiltering
=
"false"
Display
=
"false"
HeaderStyle-Width
=
"40"
/>
<
rad:GridBoundColumn
DataField
=
"SecurityId"
UniqueName
=
"SecurityId"
Display
=
"false"
HeaderText
=
"Security Id"
/>
<
rad:GridBoundColumn
DataField
=
"PriceTypeId"
UniqueName
=
"PriceTypeId"
Display
=
"false"
HeaderText
=
"Price Type Id"
/>
<
rad:GridBoundColumn
DataField
=
"AsOfDate"
ReadOnly
=
"true"
HeaderText
=
"Date"
DataFormatString
=
"{0:MM/dd/yyyy}"
ItemStyle-CssClass
=
"GridColNumber"
/>
<
rad:GridTemplateColumn
UniqueName
=
"SecurityName"
HeaderText
=
"Security"
ReadOnly
=
"true"
DataField
=
"SecurityName"
>
<
ItemTemplate
>
<
asp:HyperLink
ID
=
"hl1"
runat
=
"server"
NavigateUrl='<%# string.Format("~/SecurityXRef/SecurityXref.aspx?
menuId
=
g2
&search={0}", Eval("Ticker")) %>'>
<%# Eval("SecurityName") %>
</
asp:HyperLink
>
</
ItemTemplate
>
</
rad:GridTemplateColumn
>
<
rad:GridBoundColumn
DataField
=
"SecurityName"
UniqueName
=
"SecurityNameSimple"
HeaderText
=
"Security"
Display
=
"false"
/>
<
rad:GridBoundColumn
DataField
=
"SecurityIsin"
HeaderText
=
"ISIN"
Display
=
"false"
/>
<
rad:GridBoundColumn
DataField
=
"Ticker"
HeaderText
=
"Ticker"
ReadOnly
=
"true"
/>
<
rad:GridBoundColumn
DataField
=
"RIC"
HeaderText
=
"RIC"
ReadOnly
=
"true"
/>
<
rad:GridBoundColumn
DataField
=
"CurrencyCode"
HeaderText
=
"Currency"
ReadOnly
=
"true"
/>
<
rad:GridBoundColumn
UniqueName
=
"PrimarySource"
DataField
=
"DataSourceShortName"
ReadOnly
=
"true"
HeaderText
=
"Primary Source"
HeaderStyle-Wrap
=
"true"
/>
<
rad:GridBoundColumn
DataField
=
"PriceType"
HeaderText
=
"Price Type"
ReadOnly
=
"true"
/>
<
rad:GridTemplateColumn
HeaderText
=
"Price"
UniqueName
=
"PriceCol"
ItemStyle-CssClass
=
"GridColNumber"
DataField
=
"PriceLast"
SortExpression
=
"PriceLast"
>
<
ItemTemplate
>
<
rad:RadToolTip
ID
=
"radToolTipPrice"
runat
=
"server"
TargetControlID
=
"lnkOverride"
>
<
div
style
=
"text-align:left !important;"
>
<
strong
>Data Source: </
strong
> <%# Eval("DataSourceShortName")%><
br
/>
<
strong
>Price Type: </
strong
> <%# Eval("PriceType")%> <
br
/>
<
strong
>Field: </
strong
> <%# Eval("DataSourceFieldName")%> <
br
/>
<
strong
>Comment: </
strong
> <%# Eval("Comments")%>
</
div
>
</
rad:RadToolTip
>
<
asp:LinkButton
ID
=
"lnkOverride"
runat
=
"server"
CommandName
=
"Edit"
DataTextFormatString
=
"{0:0.000000}"
/>
</
ItemTemplate
>
<
EditItemTemplate
>
<
div
style
=
"text-align:left !important;"
>
<
strong
>Override: </
strong
><
br
/><
asp:TextBox
ID
=
"txtOverride"
runat
=
"server"
Text='<%# Eval("PriceLast","{0:0.000000}") %>'/><
br
/>
<
strong
>Comment: </
strong
><
br
/><
asp:TextBox
ID
=
"txtComment"
runat
=
"server"
TextMode
=
"MultiLine"
Text= '<%# Eval("Comments")%>' Rows="3" />
<
p
>
<
asp:CheckBox
ID
=
"chkAddHAndPrice"
runat
=
"server"
Text
=
"Add Fixed Price"
/>
</
p
>
<
asp:LinkButton
ID
=
"lnkSave"
runat
=
"server"
CommandName
=
"Update"
Text
=
"Update"
/>
<
asp:LinkButton
ID
=
"lnkCancel"
runat
=
"server"
CommandName
=
"Cancel"
Text
=
"Cancel"
/>
</
div
>
</
EditItemTemplate
>
</
rad:GridTemplateColumn
>
<
rad:GridBoundColumn
DataField
=
"JobName"
HeaderText
=
"Loader"
UniqueName
=
"Loader"
Visible
=
"false"
/>
<
rad:GridBoundColumn
DataField
=
"IsOverride"
Visible
=
"false"
/>
<
rad:GridBoundColumn
DataField
=
"PriceLast"
Display
=
"false"
/>
<
rad:GridTemplateColumn
HeaderText
=
"Bloomberg Price"
UniqueName
=
"BloombergSource"
AllowFiltering
=
"false"
ItemStyle-CssClass
=
"GridColNumber"
Display
=
"false"
HeaderStyle-Wrap
=
"true"
>
<
ItemTemplate
>
<%--<
rad:RadToolTip
ID
=
"radToolTipBbg"
runat
=
"server"
TargetControlID
=
"lblBbgSource"
>
<
div
style
=
"text-align:left !important;"
>
<
strong
>Data Source:</
strong
> <%# Eval("BbgDataSource") %>
<
br
/><
br
/>
<
strong
>Field:</
strong
> <%# Eval("BbgField") %> <
br
/>
<
strong
>Loader:</
strong
> <%# Eval("BbgJob") %><
br
/>
<
strong
>Loaded At:</
strong
> <%# Eval("BbgCreated") %>
</
div
>
</
rad:RadToolTip
>
<
asp:Label
ID
=
"lblBbgSource"
runat
=
"server"
Text='<%# Eval("BbgPrice","{0:0.000000}") %>' />--%>
<
HMC:GridPrice
Id
=
"GridPriceBbg"
runat
=
"server"
Price='<%# Eval("BbgPriceVO") %>' />
</
ItemTemplate
>
</
rad:GridTemplateColumn
>
<
rad:GridTemplateColumn
HeaderText
=
""
DataField
=
"AltSource1"
UniqueName
=
"AltSource1"
AllowFiltering
=
"false"
ItemStyle-CssClass
=
"GridColNumber"
Visible
=
"false"
HeaderStyle-Wrap
=
"true"
>
<
ItemTemplate
>
<
HMC:GridPrice
Id
=
"GridPrice1"
runat
=
"server"
Price='<%# Eval("AltSource1VO") %>' />
</
ItemTemplate
>
</
rad:GridTemplateColumn
>
<
rad:GridTemplateColumn
HeaderText
=
"Secondary Price"
DataField
=
"AltSource2"
UniqueName
=
"AltSource2"
AllowFiltering
=
"false"
ItemStyle-CssClass
=
"GridColNumber"
Visible
=
"false"
HeaderStyle-Wrap
=
"true"
>
<
ItemTemplate
>
<
HMC:GridPrice
Id
=
"GridPrice2"
runat
=
"server"
Price='<%# Eval("AltSource2VO") %>' />
</
ItemTemplate
>
</
rad:GridTemplateColumn
>
<
rad:GridTemplateColumn
HeaderText
=
"Tertiary Price"
UniqueName
=
"AltSource3"
AllowFiltering
=
"false"
ItemStyle-CssClass
=
"GridColNumber"
Visible
=
"false"
HeaderStyle-Wrap
=
"true"
>
<
ItemTemplate
>
<
HMC:GridPrice
Id
=
"GridPrice3"
runat
=
"server"
Price='<%# Eval("AltSource2VO") %>' />
</
ItemTemplate
>
</
rad:GridTemplateColumn
>
<
rad:GridTemplateColumn
HeaderText
=
"Fourth Price"
DataField
=
"AltSource4"
UniqueName
=
"AltSource4"
AllowFiltering
=
"false"
ItemStyle-CssClass
=
"GridColNumber"
Visible
=
"false"
HeaderStyle-Wrap
=
"true"
>
<
ItemTemplate
>
<
HMC:GridPrice
Id
=
"GridPrice4"
runat
=
"server"
Price='<%# Eval("AltSource2VO") %>' />
</
ItemTemplate
>
</
rad:GridTemplateColumn
>
<
rad:GridTemplateColumn
HeaderText
=
"Fifth Price"
DataField
=
"AltSource5"
UniqueName
=
"AltSource5"
AllowFiltering
=
"false"
ItemStyle-CssClass
=
"GridColNumber"
Visible
=
"false"
HeaderStyle-Wrap
=
"true"
>
<
ItemTemplate
>
<
HMC:GridPrice
Id
=
"GridPrice5"
runat
=
"server"
Price='<%# Eval("AltSource2VO") %>' />
</
ItemTemplate
>
</
rad:GridTemplateColumn
>
<
rad:GridTemplateColumn
HeaderText
=
"HMC Price"
DataField
=
"HMCPrice"
UniqueName
=
"HMCPrice"
AllowFiltering
=
"false"
ItemStyle-CssClass
=
"GridColNumber"
Display
=
"false"
HeaderStyle-Wrap
=
"true"
>
<
ItemTemplate
>
<
rad:RadToolTip
ID
=
"radToolTipHMCPrice"
runat
=
"server"
TargetControlID
=
"lblHMCPrice"
>
<
div
style
=
"text-align: left !important;"
>
<%# Eval("HMCPriceComment") %>
</
div
>
</
rad:RadToolTip
>
<
asp:Label
ID
=
"lblHMCPrice"
runat
=
"server"
Text='<%# Eval("HMCPrice.Price","{0:0.000000}") %>' />
</
ItemTemplate
>
</
rad:GridTemplateColumn
>
<
rad:GridTemplateColumn
UniqueName
=
"OpenWindow"
AllowFiltering
=
"false"
HeaderStyle-Width
=
"70"
ItemStyle-HorizontalAlign
=
"Center"
>
<
ItemTemplate
>
<
asp:LinkButton
ID
=
"LinkButton"
runat
=
"server"
CommandName
=
"OpenWindow"
Text
=
"View History"
></
asp:LinkButton
>
</
ItemTemplate
>
</
rad:GridTemplateColumn
>
<
rad:GridTemplateColumn
UniqueName
=
"OpenWindow2"
AllowFiltering
=
"false"
HeaderStyle-Width
=
"70"
ItemStyle-HorizontalAlign
=
"Center"
>
<
ItemTemplate
>
<
asp:LinkButton
ID
=
"LinkButton2"
runat
=
"server"
CommandName
=
"OpenWindow"
Text
=
"View Futures Curve"
></
asp:LinkButton
>
</
ItemTemplate
>
</
rad:GridTemplateColumn
>
<
rad:GridTemplateColumn
DataField
=
"ExceptionMessage"
ReadOnly
=
"true"
UniqueName
=
"ExceptionMessage"
HeaderText
=
"Error Description"
>
<
ItemTemplate
>
<
rad:RadToolTip
ID
=
"radToolTipException"
runat
=
"server"
TargetControlID
=
"lblExceptionMessage"
>
<
div
style
=
"text-align: left !important;"
>
<%# Eval("ExceptionMessage") %>
</
div
>
</
rad:RadToolTip
>
<
asp:Label
ID
=
"lblExceptionMessage"
runat
=
"server"
Text='<%# Eval("ShortErrorDescription") %>' />
</
ItemTemplate
>
</
rad:GridTemplateColumn
>
<
rad:GridBoundColumn
DataField
=
"Comments"
HeaderText
=
"Comments"
Display
=
"false"
/>
<
rad:GridBoundColumn
DataField
=
"DataStatusCode"
ReadOnly
=
"true"
HeaderText
=
"Data Status"
/>
<
rad:GridBoundColumn
DataField
=
"ExceptionStatusCode"
ReadOnly
=
"true"
HeaderText
=
"Exception Status"
Visible
=
"false"
/>
</
Columns
>
<
GroupByExpressions
>
<
rad:GridGroupByExpression
>
<
SelectFields
>
<
rad:GridGroupByField
FieldName
=
"MurexMkt"
FieldAlias
=
"MurexMkt"
HeaderText
=
"Murex Market"
/>
<
rad:GridGroupByField
Aggregate
=
"Count"
FieldName
=
"StagePriceId"
/>
</
SelectFields
>
<
GroupByFields
>
<
rad:GridGroupByField
FieldName
=
"MurexMkt"
/>
</
GroupByFields
>
</
rad:GridGroupByExpression
>
<
rad:GridGroupByExpression
>
<
SelectFields
>
<
rad:GridGroupByField
FieldName
=
"PrimaryTicker"
FieldAlias
=
"PrimaryTicker"
HeaderText
=
"Primary Ticker"
/>
<
rad:GridGroupByField
Aggregate
=
"Count"
FieldName
=
"StagePriceId"
/>
</
SelectFields
>
<
GroupByFields
>
<
rad:GridGroupByField
FieldName
=
"PrimaryTicker"
/>
</
GroupByFields
>
</
rad:GridGroupByExpression
>
<
rad:GridGroupByExpression
>
<
SelectFields
>
<
rad:GridGroupByField
FieldName
=
"ExceptionTypeCode"
/>
<
rad:GridGroupByField
Aggregate
=
"Count"
FieldName
=
"StagePriceId"
/>
</
SelectFields
>
<
GroupByFields
>
<
rad:GridGroupByField
FieldName
=
"ExceptionTypeCode"
/>
</
GroupByFields
>
</
rad:GridGroupByExpression
>
</
GroupByExpressions
>
</
MasterTableView
>
</
rad:RadGrid
>