Access数据库不能正确保存十进制值

问题描述 投票:3回答:4

我在尝试在Access数据库的表中保存十进制值时遇到一些问题。

如果我键入值,没有问题,但是当我尝试使用我的程序保存它们时,数据库将不会保存小数并删除,(8,7转为87)。

表中的字段是Decimal,Scale 2,Precision 8和Decimal places 2。

我正在使用此代码插入数据:

Dim price as Decimal
ProductsTableAdapter.Insert(id,name,price)

我试图把价格作为double,我仍然有同样的问题。

我已经查看了许多地方,并阅读有关将Access数据库上的数据类型更改为Double但它无法正常工作。

任何想法,将不胜感激!

编辑:

正如cybermonkey所说Decimal值是8,7所以我试图改变它。

我更改了代码以将,替换为.

Dim price2 As String
price2 = price.ToString.Replace(",", ".")
ProductTableAdapter.Insert(id, name, price2)

价格2是8.7,但数据库再次显示87,00

编辑2:

我试图用另一个数据库创建另一个项目,以确定问题是否是这个特定的适配器,但我再次遇到同样的问题。

之后,我调试程序以查看十进制值的存储方式,并且是:8,7而不是8.7。然后我尝试在数据库上插入数据,如果你把8.7or 8,7一样,它可以正常使用这两个值,所以现在我没有任何其他想法为什么这不起作用。

vb.net ms-access decimal
4个回答
2
投票

我已经能够重现这个问题。在Windows系统区域设置不使用句点字符(.)作为小数符号的计算机上运行时,它似乎是Access OLEDB提供程序的“不幸功能”。

使用以下代码

Dim price As Decimal = Convert.ToDecimal("8,7")
Dim sb As New System.Text.StringBuilder("""price"" is a ")
sb.Append(price.GetType.FullName)
sb.Append(" whose value is ")
If price < 1 Or price > 10 Then
    sb.Append("NOT ")
End If
sb.Append("between 1 and 10.")
Debug.Print(sb.ToString)

ProductsTableAdapter.Insert("myProduct", price)

当我运行Windows设置为“英语(美国)”时,我看到调试输出

"price" is a System.Decimal whose value is NOT between 1 and 10.

并且值87被插入到数据库中,因为字符串“8,7”不是该语言环境中的有效小数。

Windows设置为“西班牙语(西班牙)”,现在生成相同的代码

"price" is a System.Decimal whose value is between 1 and 10.

但值87仍然插入。

将Windows设置为“French(Canada)”时,调试输出是相同的

"price" is a System.Decimal whose value is between 1 and 10.

但是,插入失败,并且“条件表达式中的数据类型不匹配”。

通过替换实现了完全相同的结果

ProductsTableAdapter.Insert("myProduct", price)

Dim myConnStr As String
myConnStr =
        "Provider=Microsoft.ACE.OLEDB.12.0;" &
        "Data Source=C:\Users\Public\Database1.accdb"
Using con As New OleDbConnection(myConnStr)
    con.Open()
    Using cmd As New OleDbCommand("INSERT INTO Products ([name], price) VALUES (?,?)", con)
        cmd.Parameters.AddWithValue("?", "oledbTest")
        cmd.Parameters.AddWithValue("?", price)
        cmd.ExecuteNonQuery()
    End Using
End Using

证明这是System.Data.OleDb和Access OLEDB提供商之间的问题,而不仅仅是TableAdapter的特质。但是,TableAdapters似乎完全依赖于OleDb,所以不幸的是它们可能在这些条件下无法工作。

好消息是,简单地将OleDb代码转换为Odbc似乎解决了“西班牙语(西班牙)”和“法语(加拿大)”Windows语言环境的问题

Dim myConnStr As String
myConnStr =
        "Driver={Microsoft Access Driver (*.mdb, *.accdb)};" &
        "DBQ=C:\Users\Public\Database1.accdb"
Using con As New OdbcConnection(myConnStr)
    con.Open()
    Using cmd As New OdbcCommand("INSERT INTO Products ([name], price) VALUES (?,?)", con)
        cmd.Parameters.AddWithValue("?", "odbcTest")
        cmd.Parameters.AddWithValue("?", price)
        cmd.ExecuteNonQuery()
    End Using
End Using

所以一种可能的解决方法可能是使用OdbcDataAdapter而不是TableAdapter。


1
投票

问题似乎是.NET期望你为Decimal提供一个点而不是一个逗号,这是由于.NET如何处理本地化(根据this)。

这意味着.NET正在剥离,而不是插入你期望的8.7你得到87。这也解释了为什么手动将数据直接输入数据库的工作原理,但以编程方式输入数据却不行。

阅读这个问题似乎使用System.Globalization.CultureInfo.InvariantCulture可行,但是经过一段时间我能够通过将Decimalin转换为String Constant来做到这一点:

Const price As String = "8,7"
Dim price2 As String
price2 = String.Format(price, _
price.ToString(System.Globalization.CultureInfo.InvariantCulture))
ProductsTableAdapter.Insert(id,name,price)

MSDN documentation声明你还需要使用ImportGlobalization Imports System.Globalization命名空间。


0
投票

我有同样的问题,但是在C#应用程序上工作,以防万一有人遇到同样的问题我会发布对我有用的诀窍......

这真是奇怪,但我在一些论坛上找到了它,没有解释为什么它有效。

当我传递SQL命令的参数时,我所做的就是在decimal参数上添加ToString(),如下所示:

cmd.Parameters.AddWithValue("@DecimalParameter", model.DecimalParameter.ToString());

并且十进制值现在正确存储!


0
投票

根据@Astopher的说法,问题在于,.NET期望你为Decimal提供一个点而不是一个逗号,这是由于如何。因此,我将命令参数的类型更改为varchar并且它有效。

cm.Parameters.Add("@decimalcolum", OleDbType.VarChar);
cm.Parameters["@decimalcolum"].Value=decimalvalue;
cm.ExecuteNonQuery();

它在越南语,法语(法国),英语(美国)地区和语言上进行了测试。我希望这个问题解决了!

© www.soinside.com 2019 - 2024. All rights reserved.