跨数据库的C#IDataReader通用访问器

时间:2012-07-31 02:08:50

标签: c# ado.net

我正在开发一个需要使用“类似”模式连接到不同数据库类型(SQL Server,Oracle,DB2)的应用程序。我说“类似”模式的表名,列等是相同的,但底层数据类型特定于该数据库类型。例如,在SQL Server和Oracle数据库中,我都有一个名为“tablename”的表和一个名为“column”的列。 'column'的数据类型是Oracle的NUMBER和SQL Server的float。

我可以通过通用的ADO接口获取相应的提供程序工厂,连接和查询,我不确定并且遇到问题的是我应该如何访问此列。

对于Oracle,我相信我应该使用访问器函数'GetDecimal()'作为NUMBER数据类型字段,事实上似乎使用任何其他访问器,如GetInt32(),GetDouble()我得到一个强制转换异常。对于SQL Server,我应该使用访问器函数'GetDouble()'。有没有一种方法/策略来使用单一访问器函数获取此值,而不管底层数据库数据类型如何?注意,我无法控制后端数据库架构。

谢谢,感谢您的回复。

2 个答案:

答案 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等十进制值。

相关问题