public

Addressing issues in Oracle.DataAccess and AliasToBeanTransformer

  • Download Gist
OracleSQLAliasToBeanTransformer.cs
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
[Serializable]
public class OracleSQLAliasToBeanTransformer : IResultTransformer
{
const BindingFlags Flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
readonly System.Type _resultClass;
ISetter[] _setters;
readonly IPropertyAccessor _propertyAccessor;
readonly ConstructorInfo _constructor;
readonly PropertyInfo[] _fields;
public OracleSQLAliasToBeanTransformer(Type resultClass)
{
if (resultClass == null)
{
throw new ArgumentNullException("resultClass");
}
this._resultClass = resultClass;
 
_constructor = resultClass.GetConstructor(Flags, null, Type.EmptyTypes, null);
 
// if resultClass is a ValueType (struct), GetConstructor will return null...
// in that case, we'll use Activator.CreateInstance instead of the ConstructorInfo to create instances
if (_constructor == null && resultClass.IsClass)
{
throw new ArgumentException("The target class of a AliasToBeanResultTransformer "
+"needs a parameter-less constructor.", "resultClass");
}
 
_propertyAccessor = new ChainedPropertyAccessor(new[]
{
PropertyAccessorFactory.GetPropertyAccessor(null),
PropertyAccessorFactory.GetPropertyAccessor("field"),
});
 
// this is also a PERSONAL preference to only return fields that have a valid setter.
_fields = this._resultClass.GetProperties(Flags).Where(x => x.GetSetMethod() != null).ToArray();
}
 
public object TransformTuple(object[] tuple, String[] aliases)
{
// fix issue #1: aliases in Oracle CreateSQLQuery
// returns all UPPERCASE no matter your object case.
// Using the fields generated in the constructor.
if (_fields == null)
{
throw new ArgumentNullException("fields");
}
 
// this seems to address a similar issue:
// https://hibernate.onjira.com/browse/HHH-2304
// which also appears to exist in NHibernate
var fieldNames = _fields.Select(x => x.Name).ToList();
for (var i = 0; i < fieldNames.Count; i++)
{
var fieldType = _fields[i].PropertyType;
if (fieldType.IsEnum)
{
// It can't seem to handle enums, so convert them
// to Int (so the enum will work)
tuple[i] = Convert.ChangeType(tuple[i], TypeCode.Int32);
}
else
{
// set it to the actual field type on the property we're
// filling.
tuple[i] = Convert.ChangeType(tuple[i], fieldType);
}
}
 
object result;
 
try
{
if (_setters == null)
{
_setters = new ISetter[fieldNames.Count];
for (var i = 0; i < fieldNames.Count; i++)
{
var fieldName = fieldNames[i];
_setters[i] = _propertyAccessor.GetSetter(_resultClass, fieldName);
}
}
 
// if resultClass is not a class but a value type, we need to use Activator.CreateInstance
result = _resultClass.IsClass
? _constructor.Invoke(null)
: NHibernate.Cfg.Environment.BytecodeProvider.ObjectsFactory.CreateInstance(_resultClass, true);
 
for (var i = 0; i < fieldNames.Count; i++)
{
if (_setters[i] != null)
{
_setters[i].Set(result, tuple[i]);
}
}
}
catch (InstantiationException e)
{
throw new HibernateException("Could not instantiate result class: " + _resultClass.FullName, e);
}
catch (MethodAccessException e)
{
throw new HibernateException("Could not instantiate result class: " + _resultClass.FullName, e);
}
 
return result;
}
 
public IList TransformList(IList collection)
{
return collection;
}
}

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.