Неверный тип данных в выражении критериев без причины - PullRequest
0 голосов
/ 09 октября 2018

У меня эта невероятно раздражающая проблема с базой данных Access, сидящей на нашем сервере.Он работал нормально, когда вчера неожиданно начал присесть на корточки

Недопустимый тип данных в выражении критериев

  • Итак, я проверил на своей машине - работаетштраф

  • Загрузил этот рабочий код на сервер - та же ошибка

  • Скопировал базу данных на мою машину - работает нормально

Единственное различие, которое я вижу между данными, состоит в том, что если я записываю значения SQL-запроса в свое сообщение об ошибке, я вижу, что значение для Document Date имеет другой формат на моем компьютере и на сервере.:

сервер

@documentDate : 2018-10-09 12:00:00 AM 

локальный компьютер

@documentDate : 09/10/2018 12:00:00 

Все остальные значения выглядят одинаково.

Так это проблема, связанная с форматами местности / DateTime?Если это так, почему Access не может просто принять значение DateTime и сохранить его соответствующим образом, так как этот столбец имеет тип данных Date/Time.

Был бы очень признателен за помощь в этом, это сводит меня с ума.

Вот код, используемый для вставки записи:

public int InsertAod(Aod aod)
{
    if (CheckAod(aod) > 0)
    {
        Log.Message("This entry already exists");
        return 1; 
    }

    var cmd = new OleDbCommand(Constants.InsertAod);

    cmd.Parameters.AddWithValue("@company", aod.ParentCollection.Company);
    cmd.Parameters.AddWithValue("@businessUnit", aod.ParentCollection.BusinessUnit);
    cmd.Parameters.AddWithValue("@sellerGln", aod.ParentCollection.SellerGln);
    cmd.Parameters.AddWithValue("@messageId", aod.ParentCollection.MessageId);
    cmd.Parameters.AddWithValue("@documentNo", aod.ParentCollection.DocumentNumber);
    cmd.Parameters.AddWithValue("@documentDate", aod.ParentCollection.DocumentDate); // Data type of DocumentDate is DateTime
    cmd.Parameters.AddWithValue("@region", aod.ParentCollection.Region);
    cmd.Parameters.AddWithValue("@storeGln", aod.ParentCollection.StoreGln);
    cmd.Parameters.AddWithValue("@storeCode", aod.ParentCollection.StoreCode);
    cmd.Parameters.AddWithValue("@storeDescription", aod.ParentCollection.StoreDescription);
    cmd.Parameters.AddWithValue("@lineItem", aod.LineItem);
    cmd.Parameters.AddWithValue("@movementType", aod.MovementType);
    cmd.Parameters.AddWithValue("@orderNo", aod.OrderNumber);
    cmd.Parameters.AddWithValue("@reference", aod.ParentCollection.Reference);
    cmd.Parameters.AddWithValue("@barcode", aod.Barcode);
    cmd.Parameters.AddWithValue("@articleNo", aod.PnPArticleNumber);
    cmd.Parameters.AddWithValue("@vendorCode", aod.VendorProductCode);
    cmd.Parameters.AddWithValue("@articleDescription", aod.PnPArticleDescription);
    cmd.Parameters.AddWithValue("@qty", aod.PnPQuantity);

    try
    {
        //throw new Exception("how is this possible");
        return ExecuteCommand(cmd, Execute.Insert);
    }
    catch (Exception e)
    {
        var data = cmd.Parameters.Count.ToString();
        foreach (OleDbParameter parameter in cmd.Parameters)
        {
            data += $" {Environment.NewLine} {parameter.ParameterName} : {parameter.Value} {Environment.NewLine}";
        }
        Log.Error(e, $"Failed to insert AOD for {aod.OrderNumber} - {aod.LineItem}", data);
        return 0;
    }
}

Вот код для CheckAod:

public int CheckAod(Aod aod)
{
    var cmd = new OleDbCommand(Constants.CountAod);

    cmd.Parameters.AddWithValue("@orderNo", aod.OrderNumber);
    cmd.Parameters.AddWithValue("@messageId", aod.ParentCollection.MessageId);
    cmd.Parameters.AddWithValue("@lineItem", aod.LineItem);

    try
    {
        return ExecuteCommand(cmd, Execute.Count);
    }
    catch (Exception e)
    {
        Log.Error(e, "Failed to call CheckAod");
        throw;
    }
}

И ExecuteCommand, упомянутых выше:

private int ExecuteCommand(OleDbCommand cmd, Execute command)
{
    var output = 0;
    if (!(persistantConnection.State == ConnectionState.Open))
        persistantConnection.Open();

    cmd.Connection = persistantConnection;
    using (cmd)
    {                
        try
        {
            switch (command)
            {
                case Execute.Insert:
                    output = cmd.ExecuteNonQuery();
                    Log.Message("success");
                    break;
                case Execute.Count:
                    output = (int)cmd.ExecuteScalar();
                    break;
            }
        }
        catch (Exception e)
        {
            var data = cmd.Parameters.Count.ToString();
            foreach (OleDbParameter parameter in cmd.Parameters)
            {
                data += $" {Environment.NewLine} {parameter.ParameterName} : {parameter.Value} {Environment.NewLine}";
            }
            Log.Error(e, "Failed to execute command", data);
            throw;
        }
        return output;
    }
}

Вот как выглядит Constants.InsertAod:

internal const string InsertAod =
    @"INSERT INTO TAOD ([COMPANY], [BUSINESS UNIT], [SELLER GLN], [MESSAGE ID], [DOCUMENT NO],
        [DOCUMENT DATE], [REGION], [STORE GLN], [STORE CODE], [STORE DESCRIPTION], [LINE ITEM], 
        [MOVEMENT TYPE], [ORDER NO], [REFERENCE], [BARCODE], [PNP ARTICLE NO], 
        [VENDOR PRODUCT CODE], [PNP ARTICLE DESCRIPTION], [PNP QTY])
        VALUES (@company, @businessUnit, @sellerGln, @messageId, @documentNo, @documentDate, @region, 
        @storeGln, @storeCode, @storeDescription, @lineItem, @movementType, @orderNo, @reference,
        @barcode, @articleNo, @vendorCode, @articleDescription, @qty)";

И я могу подтвердить, что приведенные выше значения находятся в том же порядке, в каком они отображаются в самой БД.

1 Ответ

0 голосов
/ 10 октября 2018

После нескольких недоразумений я понял, что серверу не удалось преобразовать значение PnPQuantity из string в number (тип данных Access).

Когда я попытался это сделатьявно я получаю эту ошибку

System.FormatException: входная строка была в неправильном формате.

Даже если строка была в форме "18.000"

Я изменил свой код, добавив в него параметр CultureInfo:

decimal.Parse(aod.PnPQuantity, CultureInfo.InvariantCulture)

И теперь он работает нормально.

Что я не понимаю, так это то, почему машина вдруг может это сделать '• обрабатывать преобразование 18.000 в число, когда в настройках локализации настроено использование . в качестве десятичного разделителя:

enter image description here

Также,так как пару дней назад все работало нормально, значит, на сервере что-то изменилось, но что это может быть?

...