Access 2007 и хранение десятичного значения - PullRequest
0 голосов
/ 20 марта 2012

Я уже вижу много тем, но ни одна из них не решила мою проблему.

Я из Словении.Я использую английскую версию 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

Что хранится в БД после

DbAdapter.Update(DbData);

всегда 54.

Что еще можно попробовать?

РЕДАКТИРОВАТЬ: Кроме того, если я пытаюсь запустить этот оператор SQL непосредственно в Access:

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

Я получаю синтаксическую ошибку в операторе

Но он работает с:

UPDATE Sifrant
SET cena = 1.1
WHERE ID = 2;

Десятичный разделитель отображается как в графическом интерфейсе открытого файла accdb.

Ответы [ 2 ]

0 голосов
/ 21 марта 2012

К сожалению, у Decimal полей есть ряд проблем в Access, и обычно рекомендуется не использовать их .
Кажется, что где-то есть ошибка в том, как OleDB общается с драйвером.

После некоторого тестирования я мог бы воспроизвести вашу проблему.
Вот несколько решений:

  1. Вы уверены, что вам нужно десятичное поле в вашей базе данных?
    Кажется глупым, но вы на 100% уверены, что диапазон значений, которые необходимо сохранить в базе данных, действительно требует Decimal, а не просто Double вместо этого?
    Просто измените числовой тип вашей базы данныхполе в Access, если вам не нужно; действительно нужен десятичный тип.

  2. Используйте OleDbType.Double или OleDbType.Currency
    При определении OldDbParameter дляв этом поле используйте OledDbType.Double или OledDbType.Currency вместо OledDbType.Decimal.
    Будьте осторожны, хотя сохраненное значение может быть округлено, поэтому тщательно проверьте, если вам требуется точность, превышающая то, что .Net предлагает для этих типов.

Дополнительные тесты:

  • Я также пытался изменить культуру исполняющего потока на en-US или использовать культуру Invariant, но это не работает, проблема, похоже, заключается в конкретном несоответствии между тем, как .Net общается с ядром базы данных Jet / Ace для его обновлений.
  • Я попытался использовать Odbc вместо OleDb, но получилошибка ERROR [07006] [Microsoft][ODBC Microsoft Access Driver]Restricted data type attribute violation при использовании OdbcType.Decimal.

Тестовый код:

Я создал Access Database1.accdb с таблицей myTest, которая имеет3 поля:

  • ID, Autonumber
  • 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();
}
0 голосов
/ 21 марта 2012

Я не думаю, что это имеет какое-либо отношение к вашей локали.«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();
    }
}

Возможно, оно не совсем то, что вы ищете, но должно дать вам представление об альтернативных решениях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...