有没有办法区分.NET中的SQL Money和Decimal类型?

时间:2018-06-06 21:19:21

标签: c# .net tsql dapper closedxml

MoneyDecimal SQL类型在.NET中都被解释为Decimal。有什么办法可以区分吗?我正在尝试正确格式化Excel电子表格,但不知道哪些字段应格式化为货币,哪些应为小数。例如:

+----------------+------------------+--------------+-----------------+
| Name (VarChar) | Weight (Decimal) | Cost (Money) | Inventory (Int) |
+----------------+------------------+--------------+-----------------+
| Widget         | 3.75             | 9.99         |              25 |
+----------------+------------------+--------------+-----------------+

上面的标题包括此问题的数据类型,query是从该表中选择的存储过程:

var result = conn.Query<dynamic>(query, parameters, commandType: CommandType.StoredProcedure).ToList();

foreach (var pair in (IDictionary<string, object>)result[0]) {
  Console.WriteLine($"{pair.Key}: {pair.Value.GetType().Name}");
}

将导致:

Name: String
Weight: Decimal
Cost: Decimal
Inventory: Int32

我发现这篇文章:Money datatype and decimal type of SQL in .net但不幸的是,我没有标准化的列名,因为这意味着将任何结果集转换为Excel电子表格。

我还考虑过在需要时更改存储过程以预先挂起美元符号,但这样做的工作要多得多,而且可能会破坏其他功能。

是否有不同的方法来确定结果的SQL类型?

3 个答案:

答案 0 :(得分:1)

这是我的解决方法...

我在VS2019中创建了一个localdb(v11.0)( [TestDb]。[dbo]。[Table] )。它具有3列:

  • Id(int)
  • Number(十进制(18))
  • 美元(货币)

这是我的代码,用于获取架构,然后获取 ColumnName 及其 ProviderSpecificDataType

    [TestMethod]
    public void GetProviderSpecificDataType()
    {
        using (SqlConnection connection = new SqlConnection("Server=(localdb)\\v11.0;Integrated Security=true;"))
        {
            connection.Open();
            SqlCommand cmd = connection.CreateCommand();
            cmd.CommandText = "select * from [TestDb].[dbo].[Table]";
            SqlDataReader reader = cmd.ExecuteReader();
            DataTable table = reader.GetSchemaTable();

            var columnTypes = GetColumnTypes(table);

            Assert.AreEqual("SqlInt32", columnTypes["Id"]);
            Assert.AreEqual("SqlDecimal", columnTypes["Number"]);
            Assert.AreEqual("SqlMoney", columnTypes["Dollars"]);
        }
    }

    private Dictionary<string, string> GetColumnTypes(DataTable table)
    {
        Dictionary<string, string> data = new Dictionary<string, string>();

        foreach (DataRow row in table.Rows)
        {
            string columnName = row["ColumnName"].ToString();
            string dataType = ((Type)row["ProviderSpecificDataType"]).Name;

            data[columnName] = dataType;
        }

        return data;
    }

该测试对我来说通过了……希望这至少可以帮助您。

答案 1 :(得分:0)

之前我遇到过类似的问题,我刚刚查询了sys.columns INNER JOIN sys.types ON columns.user_type_id = types.user_type_id中的列。但看起来你正在使用存储过程。在SQL Server 2012及更高版本中,您可以使用sys.dm_exec_describe_first_result_set_for_object(@object_id,1)找到存储过程的元数据。

答案 2 :(得分:0)

我建议您在SQL的可编程性下使用类型(用户定义类型)。

您可以创建一个类型,就像我们在SQL中创建一个由名称,重量,成本和库存组成的类,在返回这些值的过程中,将它们添加到刚创建的用户定义类型中,然后将其作为集合。

并在.Net中创建一个由相同属性(名称,重量,成本和库存)组成的类,并在那里获取值。