在 NHibernate 中映射 SQLDecimal 属性
Map SQLDecimal property in NHibernate
我正在尝试从 SQL 服务器数据库中读取小数 (38,16),但遇到困难。经过大量阅读后,我尝试使用以下代码为 SQL Decimal 实现自定义类型:
public class BigDecimal : IUserType
{
public bool Equals(object x, object y)
{
return object.Equals(x,y);
}
public int GetHashCode(object x)
{
return x.GetHashCode();
}
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
int index = rs.GetOrdinal(names[0]);
object result = rs.GetValue(index);
return result;
}
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
//Not got here yet
}
public object DeepCopy(object value)
{
return value;
}
public object Replace(object original, object target, object owner)
{
return original;
}
public object Assemble(object cached, object owner)
{
return cached;
}
public object Disassemble(object value)
{
return value;
}
public SqlType[] SqlTypes { get { return new[] {SqlTypeFactory.Decimal}; } }
public Type ReturnedType { get { return typeof (SqlDecimal); } }
public bool IsMutable { get { return false; } }
}
但 rs.GetValue 的输出是小数而不是 SQLDecimal,这会导致 OverflowException。
class 看起来像这样:
public class Billy
{
public BigDecimal TheNumber {get;set;}
}
映射如下所示:
public class BillyMap : ClassMap<Billy>
{
public BillyMap()
{
Map(b=>b.TheNumber).CustomType<BigDecimal>();
}
}
谁能告诉我哪里出错了。
我认为您需要将 reader 转换为 SqlDataReader,以便您可以访问 GetSqlDecimal() 或 GetSqlValue(),因为 GetValue() 将转换为基本的 .Net Framework 类型。来自“https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.getsqlvalue%28v=vs.110%29.aspx”:
GetSqlValue returns data using the native SQL Server types. To retrieve data using the .NET Framework types, see GetValue.
最后我做了一个在 SQL 中执行转换的东西,并把它变成了 属性 部分,然后在所有映射文件上使用它:
private const string DECIMAL_CONVERSION = "(CONVERT(decimal(28,6), [{0}]))";
private static string MapDecimalProperty(string fieldName)
{
return string.Format(DECIMAL_CONVERSION, fieldName.Trim('[',']'));
}
public static PropertyPart LongDecimal(this PropertyPart part, string fieldName)
{
return part.Formula(MapDecimalProperty(fieldName));
}
映射上的:
Map(ep => ep.BigDecimalField).EDWDecimal("[BigDecimalField]");
目前有效。我已经通知数据架构团队这种情况正在发生,他们认为这不会成为任何当前数据的问题,并将考虑它用于未来的发展。
我正在尝试从 SQL 服务器数据库中读取小数 (38,16),但遇到困难。经过大量阅读后,我尝试使用以下代码为 SQL Decimal 实现自定义类型:
public class BigDecimal : IUserType
{
public bool Equals(object x, object y)
{
return object.Equals(x,y);
}
public int GetHashCode(object x)
{
return x.GetHashCode();
}
public object NullSafeGet(IDataReader rs, string[] names, object owner)
{
int index = rs.GetOrdinal(names[0]);
object result = rs.GetValue(index);
return result;
}
public void NullSafeSet(IDbCommand cmd, object value, int index)
{
//Not got here yet
}
public object DeepCopy(object value)
{
return value;
}
public object Replace(object original, object target, object owner)
{
return original;
}
public object Assemble(object cached, object owner)
{
return cached;
}
public object Disassemble(object value)
{
return value;
}
public SqlType[] SqlTypes { get { return new[] {SqlTypeFactory.Decimal}; } }
public Type ReturnedType { get { return typeof (SqlDecimal); } }
public bool IsMutable { get { return false; } }
}
但 rs.GetValue 的输出是小数而不是 SQLDecimal,这会导致 OverflowException。
class 看起来像这样:
public class Billy
{
public BigDecimal TheNumber {get;set;}
}
映射如下所示:
public class BillyMap : ClassMap<Billy>
{
public BillyMap()
{
Map(b=>b.TheNumber).CustomType<BigDecimal>();
}
}
谁能告诉我哪里出错了。
我认为您需要将 reader 转换为 SqlDataReader,以便您可以访问 GetSqlDecimal() 或 GetSqlValue(),因为 GetValue() 将转换为基本的 .Net Framework 类型。来自“https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.getsqlvalue%28v=vs.110%29.aspx”:
GetSqlValue returns data using the native SQL Server types. To retrieve data using the .NET Framework types, see GetValue.
最后我做了一个在 SQL 中执行转换的东西,并把它变成了 属性 部分,然后在所有映射文件上使用它:
private const string DECIMAL_CONVERSION = "(CONVERT(decimal(28,6), [{0}]))";
private static string MapDecimalProperty(string fieldName)
{
return string.Format(DECIMAL_CONVERSION, fieldName.Trim('[',']'));
}
public static PropertyPart LongDecimal(this PropertyPart part, string fieldName)
{
return part.Formula(MapDecimalProperty(fieldName));
}
映射上的:
Map(ep => ep.BigDecimalField).EDWDecimal("[BigDecimalField]");
目前有效。我已经通知数据架构团队这种情况正在发生,他们认为这不会成为任何当前数据的问题,并将考虑它用于未来的发展。