Access 2007 and storing decimal value

故事扮演 提交于 2019-12-12 03:19:26

问题


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:

  1. 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 a Decimal and not a simple Double instead?
    Just change the numeric type of your database field in Access if you don;t really need a Decimal type.

  2. Use OleDbType.Double or OleDbType.Currency
    When defining the OldDbParameter for that field, use OledDbType.Double or OledDbType.Currency instead of OledDbType.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 using OdbcType.Decimal.

Test code:

I created an Access Database1.accdb with a table myTest that has 3 fields:

  • ID, an Autonumber
  • ValueDecimal, defined as a Decimal with a Precision of 6
  • ValueDouble, 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!