Access数据库无法正确保存十进制值

时间:2015-01-12 11:52:23

标签: vb.net ms-access decimal

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

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

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

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

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

我试图将价格定为double,我仍然遇到同样的问题。

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

任何想法都将不胜感激!

修改

由于cybermonkey表示Decimal值为8,7,所以我尝试以这种方式进行更改。

我更改了代码以替换,的<{1}}:

.

价格2为Dim price2 As String price2 = price.ToString.Replace(",", ".") ProductTableAdapter.Insert(id, name, price2) ,但数据库再次显示8.7

编辑2:

我尝试使用不同的数据库创建另一个项目来确定问题是否是这个特定的适配器,但我又遇到了同样的问题。

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

4 个答案:

答案 0 :(得分:2)

我能够重现这个问题。它似乎是一个不幸的功能&#34;在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设置为&#34;英语(美国)&#34;我看到了调试输出

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

并将值87插入到数据库中,因为字符串&#34; 8,7&#34;不是该区域设置中的有效小数。

将Windows设置为&#34;西班牙语(西班牙)&#34;相同的代码现在生成

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

但仍然插入了值87.

将Windows设置为&#34;法语(加拿大)&#34;调试输出是相同的

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

但是,插入失败,标准表达式中的数据类型不匹配&#34;&#34;

通过替换

获得了完全相同的结果
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似乎已经解决了西班牙语(西班牙语)和#34;和#34;法语(加拿大)&#34; 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 :(得分:1)

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

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

阅读问题似乎使用System.Globalization.CultureInfo.InvariantCulture有效,但是过了一段时间我才能通过将Decimal转换为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表示您还需要使用Import Globalization命名空间Imports System.Globalization

答案 2 :(得分:0)

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

这真的很棒,但我在某个论坛上找到它并没有解释为什么会有效。

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

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

现在可以正确存储小数值!

答案 3 :(得分:0)

根据@Astopher,问题在于,.NET希望您为Decimal提供一个点而不是一个逗号,这是由于原因。因此,我将命令参数的类型更改为varchar并成功了。

// Get visitors (WORKS)
try {
    $statement = $dbh->prepare("SELECT * FROM `counter`");
    $statement->execute();
    $row_count = $statement->rowCount();
} catch(PDOException $e) {
    echo $e->getMessage();
}

// New visitor (NOT WORKING)
$ip_address = $_SERVER['REMOTE_ADDR'];
$date = date("Y/m/d H:i:s"); 

if ($row_count == 0) {
    try {
        $statement2 = $dbh->prepare("INSERT INTO `counter` (`id`, `ip_address`, `visit_date`) 
                                                    VALUES (`NULL`, `:ip_address`, `:date`)");
        $statement2->bindParam(':ip_address', $ip_address);
        $statement2->bindParam(':date', $date);
        $statement2->execute();
    } catch(PDOException $e) {
        echo $e->getMessage();
    }
}

// Show Unique Visitors (WORKS)
echo $row_count;

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