我在尝试在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.7
or 8,7
一样,它可以正常使用这两个值,所以现在我没有任何其他想法为什么这不起作用。
我已经能够重现这个问题。在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。
问题似乎是.NET期望你为Decimal
提供一个点而不是一个逗号,这是由于.NET如何处理本地化(根据this)。
这意味着.NET正在剥离,
而不是插入你期望的8.7
你得到87
。这也解释了为什么手动将数据直接输入数据库的工作原理,但以编程方式输入数据却不行。
阅读这个问题似乎使用System.Globalization.CultureInfo.InvariantCulture
可行,但是经过一段时间我能够通过将Decimal
in转换为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
命名空间。
我有同样的问题,但是在C#应用程序上工作,以防万一有人遇到同样的问题我会发布对我有用的诀窍......
这真是奇怪,但我在一些论坛上找到了它,没有解释为什么它有效。
当我传递SQL命令的参数时,我所做的就是在decimal参数上添加ToString(),如下所示:
cmd.Parameters.AddWithValue("@DecimalParameter", model.DecimalParameter.ToString());
并且十进制值现在正确存储!
根据@Astopher的说法,问题在于,.NET期望你为Decimal提供一个点而不是一个逗号,这是由于如何。因此,我将命令参数的类型更改为varchar并且它有效。
cm.Parameters.Add("@decimalcolum", OleDbType.VarChar);
cm.Parameters["@decimalcolum"].Value=decimalvalue;
cm.ExecuteNonQuery();
它在越南语,法语(法国),英语(美国)地区和语言上进行了测试。我希望这个问题解决了!