Avatar billede trumf Nybegynder
31. december 2005 - 14:22 Der er 37 kommentarer og
1 løsning

En hård lille nytårs nød at knække

Hejsa E

Jeg sidder og roder lidt med et problem, men nu må jeg altså have ander med ind over inden jeg bliver helt gal :)

jeg har et program som kalder en webservice for at checke for opdateringer osv. webservicen modtager en variabel og kalder en stored procedure som returnerer et resultat. fint nok...

Der kommer en MySql fejl ved alle kald som jeg ikke kan greje!

Koden:
webservice - .net 1.1 lavet så den returnerer en string så jeg kan læsse fejlen, normalt er det en int.

[WebMethod(Description="This service gives dealers status")]
public string xgetProgStatus(string progVersion)
{
    string status = getProgStatus2(progVersion);
    return status;
}

        private string getProgStatus2(string progVersion)
        {
            string progStatus = "0";

            MySqlConnection conn = new MySqlConnection(ConnStr);
            string cmdText = "P_GetProgVersion";
            MySqlCommand cmd = new MySqlCommand(cmdText, conn);
            cmd.CommandType = CommandType.StoredProcedure;
            MySqlParameter param;
            param = new MySqlParameter("Pversion", MySqlDbType.VarChar, 20);
            param.Value = progVersion;
            param.Direction = ParameterDirection.Input;
            cmd.Parameters.Add(param);

            try
            {
                // 1 = OK
                // 4 = der findes en nyere programversion
                // 5 = programmet skal opdateres
                // 6 = programversion mangler
                conn.Open();
                progStatus = cmd.ExecuteScalar().ToString();
            }
            catch (Exception ex)
            {
                progStatus = ex.ToString();
            }
            finally
            {
                conn.Close();
            }
            return progStatus;
        }

Stored procedure;

CREATE PROCEDURE `P_GetProgVersion` (
Pversion varchar(45)
)
BEGIN
      SELECT CASE WHEN status = NULL THEN 6
      WHEN status = 0 THEN 1
      WHEN status = 1 THEN 4
      WHEN status = 2 THEN 5 END AS vstatus
      FROM qeversion where version = Pversion;

      -- 1 = OK
      -- 4 = der findes en nyere programversion
      -- 5 = programmet skal opdateres
      -- 6 = programversion mangler
END

Fejlen:

MySql.Data.MySqlClient.MySqlException: Parameter '?' must be defined at MySql.Data.MySqlClient.MySqlCommand.SerializeParameter(PacketWriter writer, String parmName) at MySql.Data.MySqlClient.MySqlCommand.PrepareSqlBuffers(String sql) at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior) at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader() at MySql.Data.MySqlClient.MySqlCommand.ExecuteScalar() at VinGuideXML.VinGuideXML.getProgStatus2(String progVersion)


Håber nogen kan hjælpe

Godt nytår :)
Avatar billede arne_v Ekspert
01. januar 2006 - 11:06 #1
prøv og lad argument navnet starte med et ?
Avatar billede arne_v Ekspert
01. januar 2006 - 11:06 #2
param = new MySqlParameter("?Pversion", MySqlDbType.VarChar, 20);

og

CREATE PROCEDURE `P_GetProgVersion` (
?Pversion varchar(45)
)
Avatar billede trumf Nybegynder
01. januar 2006 - 16:19 #3
Hejsa Arne

Jeg har også læst mig frem til, at man i MySql 5 bruger ? foran parametre i stored procedures, men...

I deres MySql Query Browser får man en fejlmeddelse når man bruger ?

You have an error in your SQL syntax; check the manual that corresponds to your MySql server version for the right syntax to use near '?version varchar(45)
)
BEGIN
    SELECT CASE...

Det undrer mig da også at jeg har kunnet få det til at virke uden at bruge ?, dog ikke i forbindelse med webservices.

Hvis jeg prøver at køre det med ? (til trods for fejlen i MQB) får jeg en anden fejl:
MySql.Data.MySqlClient.MySqlException: Exception trying to retrieve parameter info for P_GetProgVersion: Invalid attempt to access a field before calling Read() ---> MySql.Data.MySqlClient.MySqlException: Invalid attempt to access a field before calling Read() at MySql.Data.MySqlClient.MySqlDataReader.GetFieldValue(Int32 index) at MySql.Data.MySqlClient.MySqlDataReader.GetString(Int32 index) at MySql.Data.MySqlClient.StoredProcedure.GetParameterList(String spName) at MySql.Data.MySqlClient.StoredProcedure.Prepare(String spName) --- End of inner exception stack trace --- at MySql.Data.MySqlClient.StoredProcedure.Prepare(String spName) at MySql.Data.MySqlClient.MySqlCommand.PrepareSqlBuffers(String sql) at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior) at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader() at MySql.Data.MySqlClient.MySqlCommand.ExecuteScalar() at VinGuideXML.VinGuideXML.getProgStatus2(String progVersion)
Avatar billede arne_v Ekspert
01. januar 2006 - 17:16 #4
Måske er ExecuteScalar ikke så god til SP - prøv med en command ExecuteReader,
reader Read og hent så feltet
Avatar billede trumf Nybegynder
01. januar 2006 - 17:49 #5
Det gør ingen forskel...
Avatar billede trumf Nybegynder
01. januar 2006 - 19:21 #6
Jeg fandt lige denne her http://bugs.mysql.com/bug.php?id=13753 og har opdateret til 1.0.7 dog uden nogen forbedringer!!!
Avatar billede trumf Nybegynder
08. januar 2006 - 12:48 #7
Har lige opgraderet MySql til 5.0.18 men det hjalp heller ikke. Arne er du tør for ideer ?
for så må jeg vel hellere skrive det til Mysql dev som en bug!
Avatar billede arne_v Ekspert
08. januar 2006 - 15:05 #8
hvordan ser SP og kode ud nu ?
Avatar billede trumf Nybegynder
08. januar 2006 - 17:20 #9
private string getProgStatus2(string progVersion)
        {
            string progStatus = "0";

            MySqlConnection conn = new MySqlConnection(ConnStr);
            string cmdText = "P_GetProgVersion";
            MySqlCommand cmd = new MySqlCommand(cmdText, conn);
            cmd.CommandType = CommandType.StoredProcedure;
            MySqlParameter param;
            param = new MySqlParameter("_version", MySqlDbType.VarChar, 20);
            param.Value = progVersion;
            param.Direction = ParameterDirection.Input;
            cmd.Parameters.Add(param);

            try
            {
                // 1 = OK
                // 4 = der findes en nyere programversion
                // 5 = programmet skal opdateres
                // 6 = programversion mangler
                conn.Open();
                MySqlDataReader reader = cmd.ExecuteReader();
                progStatus = reader["vstatus"].ToString();
            }
            catch (Exception ex)
            {
                progStatus = ex.ToString();
            }
            finally
            {
                conn.Close();
            }
            return progStatus;
        }

DROP PROCEDURE IF EXISTS `vinguide`.`P_GetProgVersion` $$
CREATE PROCEDURE `P_GetProgVersion`(
_version varchar(45)
)
BEGIN
      SELECT CASE WHEN status = NULL THEN 6
      WHEN status = 0 THEN 1
      WHEN status = 1 THEN 4
      WHEN status = 2 THEN 5 END AS vstatus
      FROM qeversion where version = _version;

      -- 1 = OK
      -- 4 = der findes en nyere programversion
      -- 5 = programmet skal opdateres
      -- 6 = programversion mangler
END
Avatar billede arne_v Ekspert
08. januar 2006 - 17:25 #10
og exception tekst er nu ?
Avatar billede arne_v Ekspert
08. januar 2006 - 17:25 #11
PS: 20 != 45
Avatar billede arne_v Ekspert
08. januar 2006 - 17:34 #12
MySqlDataReader reader = cmd.ExecuteReader();
              progStatus = reader["vstatus"].ToString();

skal være

                MySqlDataReader reader = cmd.ExecuteReader();
                reader.Read();
                progStatus = reader["vstatus"].ToString();
Avatar billede arne_v Ekspert
08. januar 2006 - 17:35 #13
eller måske

                MySqlDataReader reader = cmd.ExecuteReader();
                if(reader.Read())
                {
                    progStatus = reader["vstatus"].ToString();
                }
                else
                {
                    // gør noget grimt
                }
Avatar billede trumf Nybegynder
08. januar 2006 - 17:50 #14
Fejlen er stadig

MySql.Data.MySqlClient.MySqlException: Parameter '?' must be defined at MySql.Data.MySqlClient.MySqlCommand.SerializeParameter(PacketWriter writer, String parmName) at MySql.Data.MySqlClient.MySqlCommand.PrepareSqlBuffers(String sql) at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior) at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader() at VinGuideXML.VinGuideXML.getProgStatus2(String progVersion)

Det virker fint hvis jeg kalder proceduren direkte i query browseren, så det er ikke den i hvert fald. Jeg vil lige prøve at lave en app der kalder den, for at se om det er webservicen, for så må det jo være connectoren...
Avatar billede arne_v Ekspert
08. januar 2006 - 17:55 #15
og prøv at omdøb _version til ?version
Avatar billede trumf Nybegynder
08. januar 2006 - 18:10 #16
Det der med ? i variablenavene duer slet ikke med MySql Query Browser, jeg kan slet ikke få lov til at gemme en stored proc med ? i...
Avatar billede arne_v Ekspert
08. januar 2006 - 18:34 #17
hm - måske skal jeg få taget mig sammen og få installeret 5.0 ...
Avatar billede trumf Nybegynder
08. januar 2006 - 19:09 #18
Hvilken version har du nu ?
Avatar billede arne_v Ekspert
08. januar 2006 - 19:10 #19
jeg har kun 3.23 og 4.1 på min maskine nu - og de er ikke så gode
at teste stored procedures på ...

:-)
Avatar billede trumf Nybegynder
08. januar 2006 - 19:12 #20
Det skulle ikke være det store problem at opgradere fra 4.1, men den anden... :)
Avatar billede trumf Nybegynder
08. januar 2006 - 19:16 #21
3.23 skal først opgraderes til 4.0, så til 4.1 og så til sidst til 5.0
Jeg prøvede at opgradere en 4.0 til 5.0 og det tog en krig at få det til at køre...
Avatar billede trumf Nybegynder
08. januar 2006 - 19:17 #22
og så skal du være opmærksom på, at den sætter collation til latin1_swedish_ci hvis du ikke gør noget...  det er nok en skandinavisk bug!
Avatar billede arne_v Ekspert
08. januar 2006 - 19:22 #23
jeg skal slet ikke opdatere

jeg vil køre alle 3 ved siden af hinanden
Avatar billede trumf Nybegynder
08. januar 2006 - 19:41 #24
Nu skete der noget.
Jeg kunne ikke få lov til at lave en reference til den Mysql data dll som jeg hidtil har brugt, så jeg prøvede at kopiere dll fra installationsmappen over i projektmappen igen og selvom de har samme versionsnummer så var de ikke lige store, og nu er der hul igennem, bortset fra at koden ikke virker...
måske du lige vil hjælpe med det
Avatar billede trumf Nybegynder
08. januar 2006 - 19:43 #25
denne afleverer null ved forkert eller ingen serial og 1 ved den rigtigt...

SELECT CASE WHEN active = NULL THEN 2
      WHEN active = 'y' THEN 1
      WHEN active = 'n' THEN 3
      ELSE 2
      END
      AS userstatus
      FROM qeportal WHERE serial = _serial;
Avatar billede arne_v Ekspert
08. januar 2006 - 19:46 #26
skal

WHEN active = NULL

ikke være

WHEN active IS NULL

?
Avatar billede arne_v Ekspert
08. januar 2006 - 19:55 #27
jeg forstår iøvrigt ikke hvorfor du laver single SELECT i stored procedures - kunne
de ikke lige så godt fyres af i en normal SQL kommando ?
Avatar billede trumf Nybegynder
08. januar 2006 - 20:00 #28
det er fordi jeg vil holde sql for sig og kode for sig..

jeg prøver bare at gøre det hjemme som på arbit, hvor alt holdes adskilt, scriptes  og lægges i source safe
Avatar billede arne_v Ekspert
08. januar 2006 - 20:08 #29
har du fået rettet = NULL versus IS NULL og 20 versus 45 ?
Avatar billede trumf Nybegynder
08. januar 2006 - 21:02 #30
ja, men is null dur heller ikke...
der er flere ting med mysql's SQL der er anderledes end mssql's SQL!
Avatar billede trumf Nybegynder
08. januar 2006 - 21:05 #31
SELECT CASE
      WHEN active IS NULL THEN 2
      WHEN active = 'y' THEN 1
      WHEN active = 'n' THEN 3
      ELSE 2
      END
      AS userstatus
      FROM qeportal WHERE serial = '';

jeg forstår bare ikke når der er en else på og der stadig ikke kommer en talværdi ud af denne!!!
Avatar billede trumf Nybegynder
08. januar 2006 - 21:16 #32
Nåh, skidt være med det, der er hul igennem og det virker nu, jeg fanger den i en try catch...

Hvad siger du til at vi deler i porten ?
Avatar billede arne_v Ekspert
08. januar 2006 - 21:39 #33
efter at have leget lidt med min nye MySQL 5 er min konklusion at det er en
ren SQL fejl

hvis din SELECT ikke returnerer nogle rækker bliver din CASE aldig kaldt
og der er ikke noget i resultatet
Avatar billede arne_v Ekspert
08. januar 2006 - 21:40 #34
CREATE TABLE qeportal (serial VARCHAR(20), active CHAR(1));
INSERT INTO qeportal VALUES('12345678901234567890', 'y');
DELIMITER //
CREATE PROCEDURE checkserial(_serial varchar(20))
BEGIN
    SELECT CASE WHEN active IS NULL THEN 2 WHEN active = 'y' THEN 1 WHEN active = 'n' THEN 3 ELSE 2 END AS userstatus FROM qeportal WHERE serial = _serial;
END//
DELIMITER ;
CALL checkserial('12345678901234567890');
CALL checkserial('');
DELIMITER //
CREATE PROCEDURE checkserial2(_serial varchar(20))
BEGIN
    DECLARE n INTEGER;
    SELECT COUNT(*) INTO n FROM qeportal WHERE serial = _serial;
    IF n > 0 THEN
        SELECT CASE WHEN active IS NULL THEN 2 WHEN active = 'y' THEN 1 WHEN active = 'n' THEN 3 ELSE 2 END AS userstatus FROM qeportal WHERE serial = _serial;
    ELSE
        SELECT 2 AS userstatus;
    END IF;
END//
DELIMITER ;
CALL checkserial2('12345678901234567890');
CALL checkserial2('');
DROP PROCEDURE checkserial;
DROP PROCEDURE checkserial2;
DROP TABLE qeportal;
Avatar billede arne_v Ekspert
08. januar 2006 - 21:40 #35
mysql> CREATE TABLE qeportal (serial VARCHAR(20), active CHAR(1));
Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO qeportal VALUES('12345678901234567890', 'y');
Query OK, 1 row affected (0.00 sec)

mysql> DELIMITER //
mysql> CREATE PROCEDURE checkserial(_serial varchar(20))
    -> BEGIN
    ->    SELECT CASE WHEN active IS NULL THEN 2 WHEN active = 'y' THEN 1 WHEN
active = 'n' THEN 3 ELSE 2 END AS userstatus FROM qeportal WHERE serial = _seria
l;
    -> END//
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ;
mysql> CALL checkserial('12345678901234567890');
+------------+
| userstatus |
+------------+
|          1 |
+------------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> CALL checkserial('');
Empty set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER //
mysql> CREATE PROCEDURE checkserial2(_serial varchar(20))
    -> BEGIN
    ->    DECLARE n INTEGER;
    ->    SELECT COUNT(*) INTO n FROM qeportal WHERE serial = _serial;
    ->    IF n > 0 THEN
    ->        SELECT CASE WHEN active IS NULL THEN 2 WHEN active = 'y' THEN 1 W
HEN active = 'n' THEN 3 ELSE 2 END AS userstatus FROM qeportal WHERE serial = _s
erial;
    ->    ELSE
    ->        SELECT 2 AS userstatus;
    ->    END IF;
    -> END//
Query OK, 0 rows affected (0.00 sec)

mysql> DELIMITER ;
mysql> CALL checkserial2('12345678901234567890');
+------------+
| userstatus |
+------------+
|          1 |
+------------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> CALL checkserial2('');
+------------+
| userstatus |
+------------+
|          2 |
+------------+
1 row in set (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

mysql> DROP PROCEDURE checkserial;
Query OK, 0 rows affected (0.00 sec)

mysql> DROP PROCEDURE checkserial2;
Query OK, 0 rows affected (0.00 sec)

mysql> DROP TABLE qeportal;
Query OK, 0 rows affected (0.00 sec)
Avatar billede trumf Nybegynder
08. januar 2006 - 22:03 #36
Nåh ja klart, selvfølgelig ;-)

Takker, smid et svar
Avatar billede arne_v Ekspert
08. januar 2006 - 22:09 #37
svar
Avatar billede trumf Nybegynder
08. januar 2006 - 22:18 #38
Godt nytår :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Computerworld tilbyder specialiserede kurser i database-management

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester