访问2007并存储十进制值

时间:2012-03-20 12:45:15

标签: c# ms-access decimal

我已经可以看到很多主题,但没有一个能解决我的问题。

我来自斯洛文尼亚。 我使用的是英文版的Access 2007。 使用c#。

我的区域设置都设置为斯洛文尼亚语。

我有一个带十进制列的访问数据库。 当我尝试将5,4保存到其中时,它会忽略并存储54。如果我尝试将5.4存储到其中,它也会忽略。并存储54

我使用数据表来处理代码中的数据。

public static DataSet DbData;
public static DataRow DbRow;

我尝试过以下解决方案,但没有一个能够正常工作(始终使用5,4进行输入):

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

之后存储在DB中的内容
DbAdapter.Update(DbData);

总是54

我还能尝试什么?

编辑: 另外,如果我尝试直接在Access中运行此sql语句:

UPDATE Sifrant
SET cena = 1,1
WHERE ID = 2;

我在语句

中收到语法错误

但它适用于:

UPDATE Sifrant
SET cena = 1.1
WHERE ID = 2;

在打开的accdb文件的GUI中可以看到小数分隔符。

2 个答案:

答案 0 :(得分:0)

我认为它与您的语言环境无关。无论你在哪个地区,“SET cena = 1,1 ......”都不会在Access( VBA )中起作用。除非,我遗漏了一些东西。

尝试使用 OleDb 类。我认为这个(非常通用的)解决方案应该有效:

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();
    }
}

它可能不是您正在寻找的,但应该为您提供替代解决方案的想法。

答案 1 :(得分:0)

很遗憾,Decimal字段在Access中存在许多问题,通常建议使用not to use them
似乎OleDB如何与驱动程序进行对话时存在潜在的错误。

经过一些测试,我可以复制你的问题 以下是几个解决方案:

  1. 您确定数据库中需要一个十进制字段吗? 看起来很愚蠢,但您是否100%确定您需要存储在数据库中的值范围确实保证Decimal而不是简单的Double? 如果你没有,只需在Access中更改数据库字段的数字类型; t 确实需要一个十进制类型。

  2. 使用OleDbType.DoubleOleDbType.Currency
    为该字段定义OldDbParameter时,请使用OledDbType.DoubleOledDbType.Currency代替OledDbType.Decimal
    但请注意,保存的值可能是四舍五入的,因此如果您需要超出.Net为这些类型提供的精度,请进行彻底测试。

  3. 添加个人测试:

    • 我还尝试将执行线程的文化改为en-US或使用Invariant文化,但它不起作用,问题确实似乎是.Net与Jet / Ace之间的特定不匹配数据库引擎的更新。
    • 我尝试使用Odbc而不是OleDb,但在使用ERROR [07006] [Microsoft][ODBC Microsoft Access Driver]Restricted data type attribute violation时出现错误OdbcType.Decimal

    测试代码:

    我使用包含3个字段的表Database1.accdb创建了一个访问myTest

    • ID,一个自动编号
    • ValueDecimal,定义为精度为6的十进制
    • ValueDouble,定义为Double

    在运行测试之前,我将Windows区域设置切换为斯洛文尼亚语:

    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();
    }