我正在开发一个需要使用“类似”模式连接到不同数据库类型(SQL Server,Oracle,DB2)的应用程序。我说“类似”模式的表名,列等是相同的,但底层数据类型特定于该数据库类型。例如,在SQL Server和Oracle数据库中,我都有一个名为“tablename”的表和一个名为“column”的列。 'column'的数据类型是Oracle的NUMBER和SQL Server的float。
我可以通过通用的ADO接口获取相应的提供程序工厂,连接和查询,我不确定并且遇到问题的是我应该如何访问此列。
对于Oracle,我相信我应该使用访问器函数'GetDecimal()'作为NUMBER数据类型字段,事实上似乎使用任何其他访问器,如GetInt32(),GetDouble()我得到一个强制转换异常。对于SQL Server,我应该使用访问器函数'GetDouble()'。有没有一种方法/策略来使用单一访问器函数获取此值,而不管底层数据库数据类型如何?注意,我无法控制后端数据库架构。
谢谢,感谢您的回复。
答案 0 :(得分:0)
你可以使用IDataReader.GetValue,但你仍然需要在某个地方施放。您可以将访问抽象为通用包装器,并在数据读取器上使用GetSchemaTable作为机制,以便对将GetValue的结果转换为什么做出明智的决定。
答案 1 :(得分:0)
是的,你可以。考虑到您可以将两种类型(SqlServer的浮点数和Oracel的数量)转换为十进制等.NET数据类型,您可以依赖System.Convert
类中的方法。你应该这样做:
internal static decimal Read(IDbCommand cmd)
{
cmd.CommandText = @"SELECT column FROM tablename LIMIT 1";
using (var r = cmd.ExecuteReader())
{
while(r.Read())
{
return Convert.ToDecimal(r[0]);
//instead of return r.GetDecimal(0);
//or even better return r[0].ToFormattedDecimal();
}
}
}
public static decimal ToFormattedDecimal(this object d)
{
if (d is DBNull || d == null) //important line - to check DbNull
return 0; //your value
try
{
return Convert.ToDecimal(d).Normalize();
}
catch (Exception ex)
{
throw ex;
// or may be return 0;
}
}
public static decimal Normalize(this decimal d)
{
return d / 1.00000000000000000000000000000m;
}
我写了一个扩展方法,让您的工作更轻松。 Normalize
函数在末尾修剪所有不需要的零,如23.0000等十进制值。