问题
I can see alot of topics already, but none solved my problem.
I'm from Slovenia. I'm using English version of Access 2007. Using c#.
My locale settings are all set to Slovenian.
I have a access database with decimal column.
When I try to save 5,4
into it, it ignores , and stores 54
. If i try to store 5.4
into it, it also ignores . and stores 54
.
I'm using datatables to manipulate data in code.
public static DataSet DbData;
public static DataRow DbRow;
I have tried following solutions, none of them work (always using 5,4
for input):
DbRow[6] = Convert.ToDecimal(txtNovCena.Text); // value of DbRow[6] is 5,4
DbRow[6] = Decimal.Parse(txtNovCena.Text, new System.Globalization.CultureInfo("NL-nl").NumberFormat); // value of DbRow[6] is 5,4
DbRow[6] = Decimal.Parse(txtNovCena.Text, new System.Globalization.CultureInfo("EN-us").NumberFormat); // value of DbRow[6] is 54
DbRow[6] = Decimal.Parse(txtNovCena.Text, new System.Globalization.CultureInfo("sl-SI").NumberFormat); // value of DbRow[6] is 5,4
DbRow[6] = txtNovCena.Text.Replace(",", "."); // value of DbRow[6] is 54
What is stored in DB after
DbAdapter.Update(DbData);
is always 54
.
What else can I try?
EDIT: Also, if I try to run this sql statement directly in Access:
UPDATE Sifrant
SET cena = 1,1
WHERE ID = 2;
I get Syntax error in statement
But it works with:
UPDATE Sifrant
SET cena = 1.1
WHERE ID = 2;
Decimal separator is visible as , in GUI of opened accdb file.
回答1:
I do not think it has anything to do with your locale. "SET cena = 1,1..." will never work in Access (VBA) no matter which locale you are in. Unless, I am missing something.
Try using OleDb classes. I think this (very generic) solution should work:
private void UpdateRecord(string connectionString)
{
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
connection.Open();
OleDbCommand command = new OleDbCommand("UPDATE Sifrant SET cena = 1.1 WHERE ID = 2", connection);
command.ExecuteNonQuery();
}
}
It may not be exactly what you are looking for, but should provide you an idea of alternative solutions.
回答2:
Unfortunately, Decimal
fields have a number of issues in Access and it's generally recommended not to use them.
It seems like there is an underlying bug somewhere in how OleDB talks to the driver.
After some testing I could replicate your problem.
Here are a couple of solutions:
Are you sure you need a Decimal field in your database?
Seems silly, but are you 100% sure that the range of values you need to store in the database really warrant aDecimal
and not a simpleDouble
instead?
Just change the numeric type of your database field in Access if you don;t really need a Decimal type.Use
OleDbType.Double
orOleDbType.Currency
When defining theOldDbParameter
for that field, useOledDbType.Double
orOledDbType.Currency
instead ofOledDbType.Decimal
.
Be careful though that the value saved may be rounded, so test thoroughly if you require precision beyond what .Net offers for these types .
Additonal tests:
- I also tried to change the culture of the executing thread to en-US or use the Invariant culture, but it doesn't work, the issue does appear to be a specific mismatch between how .Net talks to the Jet/Ace database engine for its updates.
- I tried using Odbc instead of OleDb, but I got an error
ERROR [07006] [Microsoft][ODBC Microsoft Access Driver]Restricted data type attribute violation
when usingOdbcType.Decimal
.
Test code:
I created an Access Database1.accdb
with a table myTest
that has 3 fields:
ID
, an AutonumberValueDecimal
, defined as a Decimal with a Precision of 6ValueDouble
, defined as a Double
I switched my Windows regional settings to Slovenian before running the tests:
static void tryoledb() {
var strAccessConn = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Database1.accdb";
string strAccessSelect = "SELECT * FROM myTest";
DataSet myDataSet = new DataSet();
OleDbConnection myAccessConn = null;
myAccessConn = new OleDbConnection(strAccessConn);
OleDbCommand myAccessCommand = new OleDbCommand(strAccessSelect, myAccessConn);
OleDbDataAdapter myDataAdapter = new OleDbDataAdapter(myAccessCommand);
myAccessConn.Open();
myDataAdapter.Fill(myDataSet, "myTest");
var mytable = myDataSet.Tables["myTest"];
DataRowCollection dra = mytable.Rows;
// Set the field ValueDecimal
dra[0][1] = 5.4;
dra[1][1] = 5.4m;
dra[2][1] = decimal.Parse("5.4");
dra[3][1] = decimal.Parse("5,4");
// Set the field ValueDouble
dra[0][2] = 5.4;
dra[1][2] = 5.4m;
dra[2][2] = double.Parse("5.4");
dra[3][2] = double.Parse("5,4");
var command = new OleDbCommand("UPDATE myTest SET ValueDecimal = ?, ValueDouble = ? WHERE ID = ?", myAccessConn);
var p = command.Parameters.Add("ValueDecimal", OleDbType.Decimal); // Change to OldDbType.Double to make it work
p.SourceColumn = "ValueDecimal";
p.SourceVersion = DataRowVersion.Current;
p = command.Parameters.Add("ValueDouble", OleDbType.Double);
p.SourceColumn = "ValueDouble";
p.SourceVersion = DataRowVersion.Current;
p = command.Parameters.Add("ID", OleDbType.Integer);
p.SourceColumn = "ID";
p.SourceVersion = DataRowVersion.Original;
myDataAdapter.UpdateCommand = command;
myDataAdapter.Update(mytable);
myAccessConn.Close();
}
来源:https://stackoverflow.com/questions/9787003/access-2007-and-storing-decimal-value