We are using the RadGrid control to retrieve User objects from a repository that uses NHibernate to retrieve the objects. I am using an object data source defined as:
The method signature for GetAll is as follows:
With NHibernate, some Users are actually AdminUsers which extends User. It seems the repository is currently returning an AdminUser object first, and the control seems to be assuming then that the rest of the objects will be AdminUser rather than User. This causes the following exception to be thrown:
Is there a way to force the control to assume that data bound objects are User rather than AdminUser? Thanks!
<
asp:ObjectDataSource
ID
=
"UsersData"
runat
=
"server"
SelectMethod
=
"GetAll"
DataObjectTypeName
=
"TestingApp.Lib.Domain.User"
TypeName
=
"TestingApp.Lib.Repositories.UserRepository"
>
</
asp:ObjectDataSource
>
The method signature for GetAll is as follows:
public
IEnumerable<User> GetAll();
With NHibernate, some Users are actually AdminUsers which extends User. It seems the repository is currently returning an AdminUser object first, and the control seems to be assuming then that the rest of the objects will be AdminUser rather than User. This causes the following exception to be thrown:
"Unable to cast object of type 'TestingApp.Lib.Domain.User' to type 'TestingApp.Lib.Domain.AdminUser'."
Is there a way to force the control to assume that data bound objects are User rather than AdminUser? Thanks!
15 Answers, 1 is accepted
0
Hello Shane,
Veli
the Telerik team
Can you show us your RadGrid definition and any related code? RadGrid may refer to the first object in the collection to infer the data type of the collection, but in this case, you haev specified a generic collection, so RadGrid should know the type from the generic parameter. The exception you are getting is thrown when RadGrid cannot infer the type of the collection from the collection itself and needs to look at the type of the first element in the collection. Can you verify the DataSource passed to RadGrid is of type IEnumerable<User>, i.e. it is generic?
Veli
the Telerik team
Browse the vast support resources we have to jumpstart your development with RadControls for ASP.NET AJAX. See how to integrate our AJAX controls seamlessly in SharePoint 2007/2010 visiting our common SharePoint portal.
0

Shane
Top achievements
Rank 1
answered on 07 Dec 2010, 06:18 PM
It appears the issue is related to using IEnumerable<User>/IQueryable<User>. When I change the output type to List<User>, it works fine. Obviously I don't want to do that as it'll cause the entire table to be loaded into memory without filtering before the query. Any suggestions? :)
0
Hi Shane,
I created a small test page to try this out. What I'm getting: IEnumerable<User>, IQueryable<User> and List<User> all have RadGrid properly bind to instances of the User type and its subtype. Binding to ArrayList however throws an exception. Attaching the test page.
Veli
the Telerik team
I created a small test page to try this out. What I'm getting: IEnumerable<User>, IQueryable<User> and List<User> all have RadGrid properly bind to instances of the User type and its subtype. Binding to ArrayList however throws an exception. Attaching the test page.
Veli
the Telerik team
Browse the vast support resources we have to jumpstart your development with RadControls for ASP.NET AJAX. See how to integrate our AJAX controls seamlessly in SharePoint 2007/2010 visiting our common SharePoint portal.
0

Shane
Top achievements
Rank 1
answered on 08 Feb 2011, 09:32 PM
Thanks for the response Veli. My apologies for this lingering. I did verify that the sample you provided worked as described. While I haven't found the exact cause, I did narrow it down a little.
You can reproduce this when you are binding to an IQueryable<User> response from NHibernate.Linq<User>() request as follows:
This results in the following error:
However, if I set the DataSource to the results of the following method, it works fine:
If you have any suggestions, I am all ears at this point. Thanks!
You can reproduce this when you are binding to an IQueryable<User> response from NHibernate.Linq<User>() request as follows:
RadGrid1.DataSource = (from u
in
Session.Linq<User>()
select u).AsQueryable<User>();
This results in the following error:
[InvalidCastException: Unable to cast object of type 'UserProxy911331a3e8e141849ebd93abf294e718' to type 'TestingApp.Lib.Domain.AdminUser'.] Telerik.Web.UI.GetEnumerator>d__0.MoveNext() +137 System.Linq.Enumerable.Count(IEnumerable`1 source) +225 lambda_method(Closure ) +97 System.Linq.EnumerableExecutor`1.Execute() +94 System.Linq.EnumerableExecutor`1.ExecuteBoxed() +23 System.Linq.EnumerableQuery`1.System.Linq.IQueryProvider.Execute(Expression expression) +94 Telerik.Web.UI.GridDynamicQueryable.Count(IQueryable source) +143 Telerik.Web.UI.GridDataTableFromEnumerable.FillData35() +235 Telerik.Web.UI.GridDataTableFromEnumerable.FillData() +779 Telerik.Web.UI.GridResolveEnumerable.Initialize() +35 Telerik.Web.UI.GridResolveEnumerable.EnsureInitialized() +24 Telerik.Web.UI.GridEnumerableFromDataView..ctor(GridTableView owner, IEnumerable enumerable, Boolean CaseSensitive, Boolean autoGenerateColumns, GridColumnCollection presentColumns, String[] additionalField, Boolean retrieveAllFields) +203 Telerik.Web.UI.GridDataSourceHelper.CreateGridEnumerable(GridTableView owner, IEnumerable enumerable, Boolean caseSensitive, Boolean autoGenerateColumns, GridColumnCollection presentColumns, String[] additionalField, Boolean retrieveAllFields) +119 Telerik.Web.UI.GridDataSourceHelper.GetResolvedDataSource(GridTableView owner, Object dataSource, String dataMember, Boolean caseSensitive, Boolean autoGenerateColumns, GridColumnCollection presentColumns, String[] additionalField, Boolean retrieveAllFields) +389 Telerik.Web.UI.GridTableView.get_ResolvedDataSource() +150 Telerik.Web.UI.GridTableView.CreateChildControls(IEnumerable dataSource, Boolean useDataSource) +33 System.Web.UI.WebControls.CompositeDataBoundControl.PerformDataBinding(IEnumerable data) +66 System.Web.UI.WebControls.DataBoundControl.OnDataSourceViewSelectCallback(IEnumerable data) +128 System.Web.UI.DataSourceView.Select(DataSourceSelectArguments arguments, DataSourceViewSelectCallback callback) +33 System.Web.UI.WebControls.DataBoundControl.PerformSelect() +143 Telerik.Web.UI.GridTableView.PerformSelect() +16 System.Web.UI.WebControls.BaseDataBoundControl.DataBind() +74 Telerik.Web.UI.GridTableView.DataBind() +259 Telerik.Web.UI.RadGrid.DataBind() +87 Telerik.Web.UI.RadGrid.AutoDataBind(GridRebindReason rebindReason) +2337 Telerik.Web.UI.RadGrid.OnLoad(EventArgs e) +132 System.Web.UI.Control.LoadRecursive() +74 System.Web.UI.Control.LoadRecursive() +146 System.Web.UI.Control.LoadRecursive() +146 System.Web.UI.Control.LoadRecursive() +146 System.Web.UI.Control.LoadRecursive() +146 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2207
However, if I set the DataSource to the results of the following method, it works fine:
public
IEnumerable<User> GetUsersIEnumerable()
{
foreach
(var u
in
(from u
in
Session.Linq<User>()
select u).AsQueryable<User>())
yield
return
u;
}
If you have any suggestions, I am all ears at this point. Thanks!
0
Hi Shane,
Veli
the Telerik team
It seems the Linq to NHibernate query is returning an IQueryable containing proxy objects that cannot be cast to a derived AdminUser type. While the implementation of the NH Linq provider is beyond our scope of research, it is curious that a second iteration on the resulting IQueryable yields objects of a valid type. If you can send us some test project we can debug locally, we may be able to further investigate this issue.
Veli
the Telerik team
Browse the vast support resources we have to jump start your development with RadControls for ASP.NET AJAX. See how to integrate our AJAX controls seamlessly in SharePoint 2007/2010 visiting our common SharePoint portal.
0

Shane
Top achievements
Rank 1
answered on 09 Feb 2011, 05:14 PM
Veli,
Do you have any idea why Telerik is trying to cast to AdminUser instead of User? I do know that the first result is of the type AdminUser. But since the output type of the method is User, it seems odd that it would try to cast subsequent User objects to AdminUser.
I've tried it with and without RetrieveDataTypeFromFirstItem set to false in the MasterTableView.
I'm going to spend some time later today putting together a test project for you.
Thanks
Shane
Do you have any idea why Telerik is trying to cast to AdminUser instead of User? I do know that the first result is of the type AdminUser. But since the output type of the method is User, it seems odd that it would try to cast subsequent User objects to AdminUser.
I've tried it with and without RetrieveDataTypeFromFirstItem set to false in the MasterTableView.
I'm going to spend some time later today putting together a test project for you.
Thanks
Shane
0

Shane
Top achievements
Rank 1
answered on 11 Feb 2011, 11:15 PM
I've put together a quick project that reproduces the error. Let me know if it works for you:
http://www.mediafire.com/?kq4loge4ewcergu
Thanks!
http://www.mediafire.com/?kq4loge4ewcergu
Thanks!
0
Hi Shane,
It seems the database is missing from the App_Data folder. The solution is expecting to find a database file (Database1.mdf), but it is not in the folder.
Veli
the Telerik team
It seems the database is missing from the App_Data folder. The solution is expecting to find a database file (Database1.mdf), but it is not in the folder.
Veli
the Telerik team
Browse the vast support resources we have to jump start your development with RadControls for ASP.NET AJAX. See how to integrate our AJAX controls seamlessly in SharePoint 2007/2010 visiting our common SharePoint portal.
0

Shane
Top achievements
Rank 1
answered on 15 Feb 2011, 03:31 PM
Not 100% sure what happened, but when I zipped it up again, I verified that it included the database this time.
http://www.mediafire.com/?xw0ckzu5bt2wkq6
Thanks for your time!
http://www.mediafire.com/?xw0ckzu5bt2wkq6
Thanks for your time!
0
I got it up and running OK this time. 10x. And I am getting the exception, although the exception message says that an instance of "User" cannot be cast to an "AdminUser", not some proxy object created by NHibernate. Anyway, researching further on, it turns out that NHibernate behaves in some weird way. Particularly, the NHibernate query returns 2 different enumerators for the following 2 scenarios:
1. Cast it IEnumerable and call GetEnumerator()
2. Call GetEnumerator() directly as a method of the dynamic Linq query.
The result:
Due to the strange enumerator behavior in NHibernate, RadGrid cannot properly infer the type of the data objects in the collection. It then falls back to assuming the first data item type to be the type of all the items in the collection. The exception is the result of a failure to cast items of a base type to items in a derived type. Even though you have a generic Linq query result from GetQueryable(), RadGrid cannot identify this.
The workaround: Call ToList() to execute the query and return the actual data objects in a collection:
Now RadGrid's data source is a static list of data objects returned in a generic IEnumerable<User> collection. RadGrid can read the data object type from the generic type argument and you are getting the public properties of the User class bound to RadGrid.
Veli
the Telerik team
1. Cast it IEnumerable and call GetEnumerator()
2. Call GetEnumerator() directly as a method of the dynamic Linq query.
The result:
IEnumerable en = GetQueryable();
//enumerator type is System.Collections.ArrayList.ArrayListEnumeratorSimple
var enumerator1 = en.GetEnumerator();
//enumerator type is NHibernate.Linq.CriteriaResultReader
var enumerator2 = GetQueryable().GetEnumerator();
Due to the strange enumerator behavior in NHibernate, RadGrid cannot properly infer the type of the data objects in the collection. It then falls back to assuming the first data item type to be the type of all the items in the collection. The exception is the result of a failure to cast items of a base type to items in a derived type. Even though you have a generic Linq query result from GetQueryable(), RadGrid cannot identify this.
The workaround: Call ToList() to execute the query and return the actual data objects in a collection:
protected
void
RadGrid1_NeedDataSource(
object
sender, GridNeedDataSourceEventArgs e)
{
RadGrid1.DataSource = GetQueryable().ToList();
// Works
//RadGrid1.DataSource = GetEnumerable().Reverse(); // Works
}
Now RadGrid's data source is a static list of data objects returned in a generic IEnumerable<User> collection. RadGrid can read the data object type from the generic type argument and you are getting the public properties of the User class bound to RadGrid.
Veli
the Telerik team
Browse the vast support resources we have to jump start your development with RadControls for ASP.NET AJAX. See how to integrate our AJAX controls seamlessly in SharePoint 2007/2010 visiting our common SharePoint portal.
0

Shane
Top achievements
Rank 1
answered on 16 Feb 2011, 04:35 PM
Veli,
Thanks for the explanation. Is there a way to tell the grid what type of object it should assume rather than have it attempt to infer it from the first in the collection?
I'd like to take advantage of the IQueryable function for sorting/filtering.
Thanks for the explanation. Is there a way to tell the grid what type of object it should assume rather than have it attempt to infer it from the first in the collection?
I'd like to take advantage of the IQueryable function for sorting/filtering.
0
You cannot specify the type of the data objects explicitly. On the other hand, in .NET 3.5 and 4.0 RadGrid automatically takes advantage of the LINQ engine using IQueryable for data operations. You do not need to explicitly specify an IQueryable query as its data source.
Veli
the Telerik team
Veli
the Telerik team
0

Andy
Top achievements
Rank 1
answered on 09 Dec 2013, 09:18 PM
I have a similar issue. I have a collection of objects that are the same base type but some are sub-typed. An error is thrown when databinding, the grid is trying to cast into the incorrect sub-types. Is there a way to specify what type to use for the objects in the collection? I don't need to access any of the properties unique to the subtypes.
0
Hello Andy,
Unfortunately as my colleague Veli said you cannot specify the type of the data objects explicitly. The only way to avoid the exception is to bind the grid to collection of the base type. I am sending you a simple example which demonstrates that. Please check it out and let me know if it helps you.
Looking forward for your reply.
Regards,
Radoslav
Telerik
Unfortunately as my colleague Veli said you cannot specify the type of the data objects explicitly. The only way to avoid the exception is to bind the grid to collection of the base type. I am sending you a simple example which demonstrates that. Please check it out and let me know if it helps you.
Looking forward for your reply.
Regards,
Radoslav
Telerik
If you want to get updates on new releases, tips and tricks and sneak peeks at our product labs directly from the developers working on the RadControls for ASP.NET AJAX, subscribe to the blog feed now.
0

Andy
Top achievements
Rank 1
answered on 13 Dec 2013, 12:27 PM
Thanks for the example. I was able to convert my collection to a List<MyBaseClass> and bind it to the grid with a various subtypes in the list.