Hi !
We have our own report framework that uses a Detail View where the data is bind setting the GridControl.DataSource to a XPView that we build up with the target properties.
The values are updated correct in the Grid, however when we add a summary item to one of the columns, we get an InvalidCastException. Exactly the same code works fine in DevEx 14.2.11 so something is changed in the latest DevEx version. GridControl or GridView ?
Anything familiar ?
I am trying to debug your source code to see what is going wrong.
BR
/Stefan
Type: InvalidCastException
Message:
Unable to cast object '23,9114284515381' of type 'Double' from type 'Object' to type 'Nullable`1'. (Original Message: Specified cast is not valid.), (column Index: 4), (column Name: 'C9461'), (column Caption: 'C9461'), (column Type: System.Single), (column Unbound: False), (column UnboundExpression: ""), (PropertyDescriptor: DevExpress.Xpo.ViewPropertyDescriptor), (PropertyDescriptor Name: 'C9461'), (PropertyDescriptor PropertyType: System.Single), (PropertyDescriptor ComponentType:System.Object[]), (expectedReturnType: System.Nullable`1[[System.Single, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]) [Source:DevExpress.Data.v15.2]
Inner Exception InvalidCastException
Specified cast is not valid. [Source:DevExpress.Data.v15.2]
Stack Trace:
at DevExpress.Data.Helpers.GenericDelegateHelper.InvalidCastVerboseLogger.Impl`2.LoggedCast(Func`2 nakedCast, A arg, Func`1 exceptionAuxInfoGetter)
at DevExpress.Data.Helpers.GenericDelegateHelper.InvalidCastVerboseLogger.Impl`2.<>c__DisplayClass9.<CreateLoggedCast>b__8(A a)
at DevExpress.Data.Helpers.GenericDelegateHelper.ChainApplier.Impl`3.<>c__DisplayClasse.<ApplyChain>b__d(A a)
at System.Linq.Enumerable.<>c__DisplayClass7_0`3.<CombineSelectors>b__0(TSource x)
at System.Linq.Enumerable.<>c__DisplayClass7_0`3.<CombineSelectors>b__0(TSource x)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.Average(IEnumerable`1 source)
at DevExpress.Data.Helpers.SummaryValueExpressiveCalculator.DoTypedAverage(IEnumerable valuesEnumerable, Type valuesType, Func`1 exceptionAuxInfoGetter)
at DevExpress.Data.Helpers.SummaryValueExpressiveCalculator.Calculate(SummaryItemType summaryItemType, IEnumerable valuesEnumerable, Type valuesType, Boolean ignoreNulls, IComparer customComparer, Func`1 exceptionAuxInfoGetter)
at DevExpress.Data.DataController.CalcSummaryValue(SummaryItem summaryItem, SummaryItemType summaryType, Boolean ignoreNullValues, Type valueType, IEnumerable valuesEnumerable, Func`1 exceptionAuxInfoGetter, GroupRowInfo groupRow)
at DevExpress.Data.DataController.CalcSummaryValue(SummaryItem summaryItem, GroupRowInfo groupRow)
at DevExpress.Data.DataController.CalcSummaryInfo(GroupRowInfo groupRow, SummaryItem summaryItem, Boolean& validResult)
at DevExpress.Data.DataController.CalcTotalSummaryItem(SummaryItem summary)
at DevExpress.Data.DataController.UpdateTotalSummary(List`1 changedItems)
at DevExpress.XtraGrid.Views.Grid.GridView.SynchronizeSummary()
at DevExpress.XtraGrid.Views.Grid.GridView.OnSummaryCollectionChanged(Object sender, CollectionChangeEventArgs e)
at DevExpress.XtraGrid.Views.Grid.GridView.OnColumnSummaryCollectionChanged(GridColumn column, CollectionChangeEventArgs e)
at DevExpress.XtraGrid.Columns.GridColumn.Summary_CollectionChanged(Object sender, CollectionChangeEventArgs e)
at DevExpress.XtraGrid.GridSummaryItemCollection.OnItemChanged(CollectionChangeEventArgs e)
at DevExpress.XtraGrid.GridSummaryItem.OnChanged()
at DevExpress.XtraGrid.GridSummaryItem.SetSummary(SummaryItemType summaryType, String displayFormat, IFormatProvider format)
at DevExpress.XtraGrid.Menu.GridViewFooterMenu.OnMenuItemClick(Object sender, EventArgs e)
at DevExpress.Utils.Menu.DXMenuItem.OnClick()
at DevExpress.Utils.Menu.DXMenuCheckItem.OnClick()
at DevExpress.XtraBars.Utils.DXPopupXtraMenu.OnBarMenuClick(Object sender, ItemClickEventArgs e)
at DevExpress.XtraBars.BarItem.OnClick(BarItemLink link)
at DevExpress.XtraBars.BarBaseButtonItem.OnClick(BarItemLink link)
at DevExpress.XtraBars.BarButtonItem.OnClick(BarItemLink link)
at DevExpress.XtraBars.BarItemLink.OnLinkClick()
at DevExpress.XtraBars.BarButtonItemLink.OnLinkClick()
at DevExpress.XtraBars.BarItemLink.OnLinkAction(BarLinkAction action, Object actionArgs)
at DevExpress.XtraBars.BarButtonItemLink.OnLinkAction(BarLinkAction action, Object actionArgs)
at DevExpress.XtraBars.BarItemLink.OnLinkActionCore(BarLinkAction action, Object actionArgs)
at DevExpress.XtraBars.ViewInfo.BarSelectionInfo.ClickLink(BarItemLink link)
at DevExpress.XtraBars.ViewInfo.BarSelectionInfo.UnPressLink(BarItemLink link)
at DevExpress.XtraBars.Controls.CustomLinksControl.OnMouseUp(MouseEventArgs e)
at DevExpress.XtraBars.Controls.CustomPopupBarControl.OnMouseUp(MouseEventArgs e)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at DevExpress.XtraBars.Controls.CustomControl.WndProc(Message& msg)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Hi,
I have found another grid summary error >> "Speciefied cast is not valid" thread where a similar issue was reported. There, our customer found the cause of this issue. Please see his comment on November 28 2015 and check if the issue you are experiencing is caused by the same reason. If not, provide us with a data base table structure to which your XPView is bound and illustrate how you populate XPView.
I look forward to your response.
After debugging I see that the target object is Nullable Single but the source is Nullable Double, that's why we get the exception. Apparently you have done some changes somewhere, that's why we face this problem now.
In this particular case we have PersistentAlias properties like below and the Avg becomes a Double :
[PersistentAlias("AnimalDailys[DateAndTime >= Last7Days() AND DateAndTime < DDMToday() AND TotalYield > 0 AND IsYieldValid = True].Avg(TotalYield)"), VisibleInListView(false)] [ReportItem] public Single SevenDayAverage { get { return Convert.ToSingle(EvaluateAlias(PropertySevenDayAverage), CultureInfo.InvariantCulture); } }
I can solve this by adding a conversion to Float of the result value, but then we need to go through all those similar properties and do the same. Can you propose some other solution to this problem ?
Is there some way to force the properties to become Double already while adding the properties to the XPView ?
BR
/Stefan
Hello Stefan,
In fact, this code should not work in version 14.2 either. The problem is that the XPView determines the property type from metadata as Single, but the expression evaluated on the database server returns values of another type. This inconsistency makes it difficult for XtraGrid to choose the correct summary calculation method. I have attached the sample project demonstrating that this issue is not specific to the latest version of DevExpress controls.
The best solution in this situation would be to change the aliased property type to match the alias expression type. If the expression is evaluated as Decimal, let the property type be Decimal. If this is not possible in your case and you would like to avoid modifying persistent alias expressions as well, I suggest that you use the same expression in the XPView's property definition instead of referencing the SevenDayAverage property directly. This is not the best solution, but it will work.
This is what we do actually in our reporting framework. We store the PersistentAlias as report items in the database which are then accessed when creating the reports. So how can I control the data type of this expression queried in the database, i.e. is it possible to do that while populating the properties of the XPView with ViewProperty ?
In this case it's apparently treated as double but we want to change it to be float (single) to match the GridColumn.
The ViewProperty type depends on the result type of the expression assigned to its Property property. The result type of the expression depends on types of properties and values used in this expression. For example:
xpView.Properties.AddRange(new ViewProperty[] { new ViewProperty("PropertyA", SortDirection.None, "SevenDayAverage", false, true), new ViewProperty("PropertyB", SortDirection.None, "AnimalDailys[DateAndTime >= Last7Days() AND DateAndTime < DDMToday() AND TotalYield > 0 AND IsYieldValid = True].Avg(TotalYield)", false, true) });
The code above adds two properties. Both of them return the same value, because the SevenDayAverage property is an alias for the expression used in the PropertyB property. However, the PropertyA property type is Single, because the expression depends on the SevenDaysAverage property, whose type is Single. The PropertyB property type depends on the AggregatedExpression, which is a simple property operand. Hence, if the TotalYield property type is Decimal, the PropertyB type will also be Decimal.
You will not experience any issue using the PropertyB, while PropertyA may cause incorrect behavior in some scenarios because its value type does not match the declared property type. That is why, I suggested changing the SevenDayAverage property type to Decimal as the most correct solution.
It's the alternative with PropertyB we use and TotalYield is of type float so it's strange that it doesn't work then !?
After debugging I found out that the SummaryItem.ColumnInfo.Type is Single so that is correct. The problem is in the DataController.cs, CalcSummaryValue(), where it should get the value on line 2380.
[ReportItem(Aggregate = Aggregate.Sum)] [DbType("real")] public float TotalYield { get { return _totalYield; } set { SetPropertyValue<float>(ColumnTotalYield, ref _totalYield, value); } }
How does it work for enums, then you have most likely an int type in the database so it need to be casted to the enum type in the GridColumn ?
And as I wrote before, it works in 14.2 because that's the version we have in the current release version.
Since the value is shown correct in the GridColumn it's only an issue with the calculation of the SummaryItem which somehow is changed in the latest version.
Chan ging the type of the property will have a big impact on the legacy code so that is not a way forward. For us this is not good that we face these kidn of breaking changes when upgrading the Dev Express version.
If the TotalYield property type is float, then your code is correct and you do not need to change SevenDayAverage property type. In this situation, there indeed must be some kind of change in our code, which caused the exception. Let me research this issue further and discus it with our R&D team. Perhaps, we will need additional details about the error. I will get back to you when we find a solution of if we have any questions.
We have determined the conditions under which this exception might occur and our developers are going to fix this issue. For this purpose, I have created a separate ticket on your behalf that describes the issue in detail: XPView might return value of the type different than the property type if the AggregateOperand is used in the expression. The issue that you described in this ticket is most likely related to that issue and will be resolved as well. Let's wait when our developers finish their research.