'Oracle.DataAccess manage c# byte fields as signed
Recently, adapting a .NET application to Oracle, I've found that the .net fields typed as byte, are updating (or inserting) in database as Signed Bytes, so a (byte)200 is set as -56 on the Oracle Column, that is defined as NUMBER(3,0) (due to legacy database definition).
Sample of wrong code:
var command = session.Session.Connection.CreateCommand();
command.CommandType = System.Data.CommandType.Text;
command.CommandText = "UPDATE MyTable SET TblByteCol = :parByte WHERE Id = 15";
var parameter = command.CreateParameter();
parameter.ParameterName = "parByte";
parameter.Value = (byte)200;
command.Parameters.Add(parameter);
var result = command.ExecuteNonQuery();
That code (similar) sets a -56 on TblByteCol. And when I try to get that value, it throws an OverflowException.
I'm using NHibernate (the above code is only to check that the problem is on driver) and I've found a solution defining a IUserType (from this SO Thread), but I would know (and understand) if is there any cleaner solution and more native solution. Perhaps an updated version of Oracle.DataAccess (I've been searching but no references found).
Versions:
- .NET Framework: 4.0
- Oracle.DataAccess: 4.112.1.0
- NHibernate: 3.3.5.4
My solution
public class OracleUnsignedByte : IUserType
{
public object Assemble(object cached, object owner)
{
return cached;
}
public object DeepCopy(object value)
{
return value;
}
public object Disassemble(object value)
{
return value;
}
public new bool Equals(object x, object y)
{
if (ReferenceEquals(x, y)) return true;
if (x == null || y == null) return false;
return x.Equals(y);
}
public int GetHashCode(object x)
{
return x == null ? typeof(string).GetHashCode() + 473 : x.GetHashCode();
}
public bool IsMutable
{
get { return false; }
}
public object NullSafeGet(System.Data.IDataReader rs, string[] names, object owner)
{
var obj = NHibernateUtil.String.NullSafeGet(rs, names[0]);
if (obj == null) return null;
short shortObj = Convert.ToInt16(obj);
// Expected spanish format from DB
if (shortObj < 0)
{
return Convert.ToByte(256 + shortObj);
}
return Convert.ToByte(obj);
//throw new SegTechnicalException(string.Format("Cannot convert string '{0}' to DateTime.", dateTimeStr));
}
public void NullSafeSet(System.Data.IDbCommand cmd, object value, int index)
{
if (value == null)
{
((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value;
}
else
{
((IDataParameter)cmd.Parameters[index]).Value = (byte)value;
}
}
public object Replace(object original, object target, object owner)
{
return original;
}
public Type ReturnedType
{
get { return typeof(byte); }
}
public NHibernate.SqlTypes.SqlType[] SqlTypes
{
get { return new[] { NHibernateUtil.String.SqlType }; }
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
