Tedious: Azure MS SQL bekommt völlig andere Dezimalzahlen

Erstellt am 12. Dez. 2019  ·  21Kommentare  ·  Quelle: tediousjs/tedious

Hallo zusammen,

Ich hatte ein Bereichsfehlerproblem, das mich zwang, mühsam auf Version 6.5.0 zu aktualisieren (ich habe versucht, auf 6.6.1 zu aktualisieren, aber das hat nicht geklappt, siehe Problem Nr. 1008).

Wenn ich jetzt versuche, einen hohen Dezimalwert zu speichern, wird daraus eine andere, viel kleinere Zahl.

18728.4 wird zu 281.655926290
21345.4 wird zu 2898.655926290
625348.4 wird zu 16605.845567585
&
34348.42 wird zu 15901.675926290

Es ist verdächtig, wie oft sie mit 5926290 enden.
Wenn die Ausführung an die Konsole gesendet wird, sehe ich tatsächlich den richtigen Wert. So ändert es sich auf dem Weg nach der Abfrage und in die db.

POSTing 12304.53 funktioniert tatsächlich und wird einfach so in die DB geschrieben.

Ich benutze es in Kombination mit
Fortsetzung 5.15.1
Typoskript: 3.3.4000
Knoten: 10.15.3
eine Azure MS SQL-Datenbank

und das Feld ist definiert als

numResult: {
        type: DECIMAL(18, 9),
    },

Das sagt auch die MS-SQL-Datenbank zu diesem Feld.

Lassen Sie mich wissen, wenn Sie zusätzliche Informationen benötigen

Response needed

Alle 21 Kommentare

Wenn Sie also den Wert über ein anderes Tool in der Datenbank überprüfen, ist der geschriebene Wert falsch? Ich werde versuchen, einen Testfall dafür zu schreiben.

Nun, ich benutze meinen NodeJs-Sequelize-Server, um den Wert zu schreiben, und ich sehe auch die Abfrage, wo der Wert korrekt ist.

Dann sehe ich mit DBeaver den falschen Wert in der DB.
GET mit sequelize gibt natürlich auch den falschen Wert zurück.

@arthurschreiber fyi Ich habe auf mühsame v6.6.1 aktualisiert, nachdem ich das in #1008 beschriebene Problem behoben hatte. Hat bei diesem Problem aber keinen Unterschied gemacht

Hat jemand einen Hinweis, warum dies passieren könnte und/oder wie eine Problemumgehung aussehen könnte?

@obermobber Ich schaue sobald ich kann.

Okay, danke @arthurschreiber ! Es macht mich einfach wahnsinnig haha

@obermobber Ich habe versucht, dies zu reproduzieren, aber es gelingt mir nicht.

Ich habe den Dezimaltests in test/integration/parameterised-statements-test.js neue Testfälle mit den Werten hinzugefügt, die Sie in dieser Ausgabe gepostet haben, aber sie werden korrekt an den SQLServer gesendet.

Können Sie das Problem, das Sie sehen, in einem einfachen Testfall destillieren? 🙇

@arthurschreiber Schande über mich, aber ich habe in meinem kurzen Entwicklerleben noch nie einen einzigen Test geschrieben (es ist schlecht, ich weiß ...). Aber ich würde mehr als glücklich sein, alle notwendigen Informationen zur Verfügung zu stellen :(

Es muss kein Testfall sein, der in dem Framework geschrieben ist, für das wir mühsames Testen verwenden.

Ich brauche nur die minimale Menge an Code, die es mir ermöglichen würde, dieses Problem zu reproduzieren. 😄

Also, ich hoffe, ich habe das richtig verstanden.

Alles, was ich ausführe, ist Folgendes:

@Post('/test')
    private async postDecimalTest(
        @Body() body: testCaseBody
    ) {
        try {
            const transaction = await sequelize.transaction();

            await DB.TestExecutionValues.create({
                testId: body.testId,
                numResult: body.numResult,
                strResult: body.strResult,
                enumResultSid: body.enumResult,
                unitId: body.unitId,
                ynPassed: body.ynPassed,
                comment: body.comment,
            }, { transaction });

            await transaction.commit();
            return { message: 'success posting test' };
        } catch (e) {
            console.log(e);
            throw e;
        }
    }

Ich sende diesen Körper:

{
    "testId": "LEVEL",
    "numResult": 465324.75,
    "strResult": "testcase",
    "enumResult": "1",
    "unitId": "m³",
    "ynPassed": 1,
    "comment": ""
}

Folgendes wird protokolliert:

Executing (036ca06b3c1869b4851b): BEGIN TRANSACTION;
Executing (036ca06b3c1869b4851b): INSERT INTO [TestExecutionValues] ([testId],[numResult],[strResult],[enumResultSid],[unitId],[ynPassed],[comment]) OUTPUT INSERTED.* VALUES (<strong i="13">@0</strong>,<strong i="14">@1</strong>,<strong i="15">@2</strong>,<strong i="16">@3</strong>,<strong i="17">@4</strong>,<strong i="18">@5</strong>,@6);
Executing (036ca06b3c1869b4851b): COMMIT TRANSACTION;

und das steht in der DB:

{
                "testId": {
                    "id": "LEVEL",
                    "description": null
                },
                "numResult": 4156.148157261,
                "strResult": "testcase",
                "enumResult": {
                    "id": "#N/A",
                    "description": null
                },
                "unit": {
                    "id": "m³",
                    "description": null
                },
                "ynPassed": true,
                "comment": ""
}

also wird aus 465324,75 4156,148157261

Ich verwende Routing-Controller 0.7.7 für die Anfragen, falls das wichtig zu wissen ist.
Benötigen Sie weitere Informationen? (oder war das ganze überhaupt richtig?)

+++BEARBEITEN+++

Dachte, Sie brauchen vielleicht die Tabellendefinition:

const TestExecutionValues = sequelize.define('TestExecutionValues', {
    sid: {
        type: INTEGER,
        autoIncrement: true,
        primaryKey: true,
        allowNull: false,
    },
    testId: {
        type: STRING,
        references: {
            model: Tests,
            key: 'testId',
        },
    },
    numResult: {
        type: DECIMAL(18, 9),
    },
    strResult: {
        type: STRING,
    },
    enumResultSid: {
        type: INTEGER,
        references: {
            model: EnumResults,
            key: 'sid',
        },
    },
    unitId: {
        type: STRING,
        references: {
            model: Units,
            key: 'unitId',
        },
    },
    ynPassed: {
        type: BOOLEAN,
    },
    comment: {
        type: TEXT,
    },
}, {
    timestamps: false,
});

Es sieht so aus, als würden Sie sequelize zusätzlich zu langweilig verwenden. Dies macht es oft schwieriger, Probleme aufzuspüren, da es mehr bewegliche Teile gibt, an denen etwas schief gehen könnte. 😞

Wie wird DB.TestExecutionValues implementiert? 🤔

Ah, du hast gerade die Definition gepostet. Ich sehe was ich tun kann.

Ja, ich benutze mühsam als DB-Treiber für Sequelize.
Wenn es hilfreich ist, ist dies ein DBeaver-Screenshot des Felds:

Bildschirmfoto 2019-12-14 um 12 20 05

Hier ist ein Beispiel, das ich gerade aufgepeppt habe:

const { Connection, Request, TYPES: { Decimal } } = require('tedious');

const connection = new Connection({
  // ...
});

connection.on('connect', () => {
  const request = new Request('CREATE TABLE #decimals (value decimal(18, 9))', (err) => {
    if (err) {
      throw err;
    }

    const request = new Request('INSERT INTO #decimals (value) VALUES (@value)', (err) => {
      if (err) {
        throw err;
      }

      const request = new Request('SELECT * FROM #decimals', (err) => {
        if (err) {
          throw err;
        }

        connection.close();
      });

      request.on('row', (columns) => {
        console.log(columns);
      });

      connection.execSql(request);
    });

    request.addParameter('value', Decimal, 18728.4, { precision: 18, scale: 9 });

    connection.execSql(request);
  });

  connection.execSqlBatch(request);
});

und das ist die Ausgabe, die ich zurückbekomme:

[ { value: 18728.4,
    metadata:
     { userType: 0,
       flags: 9,
       type: [Object],
       collation: undefined,
       precision: 18,
       scale: 9,
       udtInfo: undefined,
       dataLength: 17,
       schema: undefined,
       colName: 'value',
       tableName: undefined } } ]

Ich glaube wirklich nicht, dass dies ein Problem mit tedious ist. 🤔 Sie können vielleicht versuchen, denselben Code mit Ihrer Datenbank auszuführen und zu sehen, ob Sie andere Ergebnisse erhalten?

Welche Version von tedious verwendest du über sequelize ?

hmm... das probiere ich mal aus, danke!

Momentan hängengeblieben
RequestError: Requests can only be made in the LoggedIn state, not the SentPrelogin state

Aber während ich versuche, das zu beheben, ist hier ein Schnappschuss meiner Paketsperre (mühsam ist nicht in den Abhängigkeiten von sequelize aufgeführt, dies ist das einzige Vorkommen von langweilig in meiner Paketsperre):

"tedious": {
      "version": "6.6.2",
      "resolved": "https://registry.npmjs.org/tedious/-/tedious-6.6.2.tgz",
      "integrity": "sha512-0Yziuys2h66dVlqMPJpNFciQ/N2VrgwY8o8TXyj4OZBaxrvqRPeMuTKZZVBFTGOjt/J15fR0fX0HBnCHjm7QWA==",
      "requires": {
        "@azure/ms-rest-nodeauth": "2.0.2",
        "@types/node": "^12.7.11",
        "@types/readable-stream": "^2.3.5",
        "bl": "^3.0.0",
        "depd": "^2.0.0",
        "iconv-lite": "^0.5.0",
        "jsbi": "^3.1.1",
        "native-duplexpair": "^1.0.0",
        "punycode": "^2.1.0",
        "readable-stream": "^3.4.0",
        "sprintf-js": "^1.1.2"
      },

Oh, wenn Sie den Code wie folgt ändern:

const { Connection, Request, TYPES: { Decimal } } = require('tedious');

const connection = new Connection({
  // ...
});

connection.on('connect', (err) => {
  if (err) {
    throw err;
  }

  const request = new Request('CREATE TABLE #decimals (value decimal(18, 9))', (err) => {
    if (err) {
      throw err;
    }

    const request = new Request('INSERT INTO #decimals (value) VALUES (@value)', (err) => {
      if (err) {
        throw err;
      }

      const request = new Request('SELECT * FROM #decimals', (err) => {
        if (err) {
          throw err;
        }

        connection.close();
      });

      request.on('row', (columns) => {
        console.log(columns);
      });

      connection.execSql(request);
    });

    request.addParameter('value', Decimal, 18728.4, { precision: 18, scale: 9 });

    connection.execSql(request);
  });

  connection.execSqlBatch(request);
});

Sie sollten eine bessere Fehlermeldung sehen, wenn die Verbindung fehlschlägt.

Das hat tatsächlich sehr geholfen, ich hatte die Eigenschaft encryption nicht.

Folgendes sollte richtig sein oder?

const connection = new Connection({
    server: 'server',
    authentication: {
        type: 'default',
        options: {
            userName: 'user',
            password: 'password',
        }
    },
    options: {
        encrypt: true,
        database: 'dbname'
    }
});

Ich habe die gleichen Anmeldeinformationen mit DBeaver verwendet und habe keine Probleme, aber ich bekomme immer ConnectionError: Login failed for user 'user'.
Der einzige Unterschied in meinem Sequelize-Verbindungsaufbau ist die Dialektoption, aber die habe ich hier nicht gefunden: http://tediousjs.github.io/tedious/api-connection.html

Ich bitte um Verzeihung für die ganzen Schwierigkeiten!

Das sollte stimmen! Ist der Benutzer, den Sie verbinden, ein SQLServer-Benutzer oder ein Azure Active Directory-Kontobenutzer? (In Azure-Datenbanken kann es beides/beides geben). Versuchen Sie, anstelle von default azure-active-directory-password als Authentifizierungstyp azure-active-directory-password zu verwenden.

Das brachte mich einen Schritt näher. Jetzt bekomme ich (node:67210) UnhandledPromiseRejectionWarning: ConnectionError: Security token could not be authenticated or authorized.
Dies scheint jedoch eher ein Problem auf der Azure-Konfigurationsseite zu sein. (Zumindest führt mich Google dorthin, haha)

In Bezug auf dieses Problem scheint alles auf einen anderen als langweiligen Fehler hinzudeuten, also könnten wir das meinerseits schließen und ich würde wahrscheinlich ein Problem mit sequelize ansprechen.

Ich weiß die Zeit, die du dir genommen hast, sehr zu schätzen @arthurschreiber !!

Hm. Ich frage mich immer noch, warum Sie eine Verbindung mit sequelize herstellen können, aber nicht mit tedious . 😬

Sie können dieses Problem gerne schließen und erneut öffnen, sobald Sie sicher sind, dass das Problem von tedious kommt. 🙇

Ich würde nicht nein sagen, dieses Rätsel mit dir zu lösen, haha! Aber ich wollte euch nicht noch mehr Zeit in Anspruch nehmen 😃

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen