|
From: NHibernate J. <nh...@gm...> - 2008-06-13 12:59:12
|
QueryTranslator: Invalid Cast to object array when using IResultTransformer
---------------------------------------------------------------------------
Key: NH-1344
URL: http://jira.nhibernate.org/browse/NH-1344
Project: NHibernate
Issue Type: Patch
Components: Core
Affects Versions: 2.0.0.Alpha1, 1.2.1, 1.2.0.GA, 2.0.0.Alpha2, 2.0.0.GA
Reporter: Stefan Simroth
Priority: Minor
Attachments: QueryTranslatorInvalidCastToObjectArray20trunk.patch
there seems to be an issue with a hard cast in the QueryTranslator
class, line 1452 (trunk) - resp. line 1288 (1.2.1) ...
The hard cast in method GetResultList to an object[] fails in the case
of my company's product, when using an IResultTransformer.
I chose to use an IResultTransformer implementation for Criteria's and
Query's to be able to set a required property. It seems an appropriate
way to me and my tests (and the running app) ensure that it works.
However, I had to patch the QueryTranslator at the locations mentioned
above, because it threw an invalid cast exception (stacktrace below) -
because the IList of my objects could not be casted to an object[].
Debugging it, showed me that the "results" list contained my domain
objects, but it could not be casted to an object[]. It was a collection
of my domain types and my domain types are no object[]. Now, some time
passed by since then, and our product works fine with the patch, so
unfortunately I forgot the exact reason, but I'd guess, I used the
generic Query signature and so the results list was a generic list that
cannot be casted to object[]. But also ArrayList or Hashtable cannot be
casted to object[]...
A little experiment, gave me the compiler error:
Cannot convert type
'System.Collections.Generic.List<ConsoleApplication1.Project>' to 'object[]'
class Program
{
static void Main(string[] args)
{
List<Project> projects = new List<Project>();
object[] objs = (object[]) projects;
}
class Project { }
}
=> same thing doesn't work with ArrayList or Hashtable ...
----
The code snippet from QueryTranslator in question:
for (int i = 0; i < results.Count; i++)
{
object[] row = (object[]) results[i];
results[i] = holderInstantiator.Instantiate(row);
}
----
Patch - with a "safe" cast:
object[] row = results[i] as object[];
if (row != null)
{
results[i] = holderInstantiator.Instantiate(row);
}
The included patch is for the NHibernate 2.0 trunk.
The same problem exists in earlier versions, namely 1.2.
I might be totally missing the root of the problem, but please excuse
this, as I am not familiar with the NHibernate internals, but tried to
apply a patch at the right place to enable the very useful feature of
the IResultTransformer to our case - and maybe to others in future.
Here is the stacktrace: (version 1.2.1)
at NHibernate.Hql.Classic.QueryTranslator.GetResultList(IList
results, IResultTransformer resultTransformer) in
d:\dev\yap\nhibernate\trunk\src\NHibernate\Hql\Classic\QueryTranslator.cs:line
1291
at NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor
session, QueryParameters queryParameters) in
d:\dev\yap\nhibernate\trunk\src\NHibernate\Loader\Loader.cs:line 1744
at NHibernate.Loader.Loader.List(ISessionImplementor session,
QueryParameters queryParameters, ISet querySpaces, IType[] resultTypes)
in d:\dev\yap\nhibernate\trunk\src\NHibernate\Loader\Loader.cs:line 1738
at NHibernate.Hql.Classic.QueryTranslator.List(ISessionImplementor
session, QueryParameters queryParameters) in
d:\dev\yap\nhibernate\trunk\src\NHibernate\Hql\Classic\QueryTranslator.cs:line
1124
at NHibernate.Impl.SessionImpl.Find(String query, QueryParameters
parameters, IList results) in
d:\dev\yap\nhibernate\trunk\src\NHibernate\Impl\SessionImpl.cs:line 1763
----
My IResultTransformer implementation:
#region IResultTransformer Members
public object TransformTuple(object[] tuple, string[] aliases)
{
object o = CriteriaUtil.RootEntity.TransformTuple(tuple, aliases);
TrySetDomainModelStore(o);
return o;
}
public IList TransformList(IList collection)
{
for (int i = 0; i < collection.Count; i++)
{
TrySetDomainModelStore(collection[i]);
}
return collection;
}
#endregion
TranformTuple is called rarely. TransformList is called after the
HolderInstantiator call.
I never create a new MyEntity[] { my, domain, entities}, nor a new
object[] { my, domain, entities} ...
------
Felix Gartsman:
Isn't this similar to Hibernate issues:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2463
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2525
They are also present in NH, and they prevent caching queries with
IResultTransformer - the caching thinks it gets a tuple, but it's actually
the transformed object.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.nhibernate.org/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
|