Avatar billede quiw Nybegynder
06. december 2006 - 10:39 Der er 27 kommentarer og
1 løsning

Database crasher.

Hejsa Eksperter, jeg er ved at udvikle et multiplayer rollespil som fungerer over telnet som tekst .. Eller også det man kaldet et "MUD", det går nu udmærket, men er løbet ind i et problem ..

- Problemet er, at næsten alt hvad clienten foretager sig bliver skrevet eller loadet i database, f.eks. loader den Experience, Level, Position og en maaasse andre ting. Det fungere sådan her:

Startdatabase();
Skriv/Læs til database;
Lukdatabasen;

Og det gør jeg hver gang jeg skal bruge information fra databasen, men problemet er at når flere logger på, så åbner databasen flere gange oven i hinanden og crasher, kan det problem løses?
Avatar billede nicklasw Nybegynder
06. december 2006 - 10:59 #1
er det c eller c++?
hvis det er c++ har jeg måske en idé...
skal lige siges at jeg ikke er så hardcore til c++ i nu...
Avatar billede quiw Nybegynder
06. december 2006 - 11:14 #2
Det er C++ :)
Avatar billede mcgoat Nybegynder
06. december 2006 - 11:23 #3
Hvilken DB er det?
Avatar billede nicklasw Nybegynder
06. december 2006 - 11:30 #4
kan du så ikke bare lave en class hvor du åbner DB'en og laver en function der skriver til den... så kan du bare kalde class'en en gang, så åbner forbindelsen og så hver gang du skal skrive til databasen bruger du bare functionen i din class...

er det fuldstændig uforståligt? for så må jeg jo prøve at omformulere mig ;)
Avatar billede nicklasw Nybegynder
06. december 2006 - 11:36 #5
noget alla det her...

class DB
{
    DB{
      //åben databasen
      }

  ~DB{
      //luk database
      }

    void skriv(string brugernavn){
      //skriv bruger info til databasen
      //brug argumentet til at finde ud hvilken bruge det er du skal skrive til
      }
}
Avatar billede quiw Nybegynder
06. december 2006 - 11:37 #6
mcgoat - Det er en microsoft access database
nicklasw - Det er også lidt det i princippet jeg gør, jeg har lavet en "void" funktion til det ..
Avatar billede nicklasw Nybegynder
06. december 2006 - 11:42 #7
idéen er lidt, at du kun skal kalde class'en en gang, der ved åbner du kun databasen en gang...

(nu kan jeg ikke huske hvad det hedder at kalde en class'e)
Avatar billede quiw Nybegynder
06. december 2006 - 11:45 #8
nicklasw - Jeg har lavet en almindelig void funktion som ser sådan her ud:

void startdatabase()
{
  // start database kode
}

void skrivtildatabase()
{
  // Skriv til database kode
}

void lukdatabase()
{
  // Luk database kode
}


int main()
{
    startdatabase();
    skrivtildatabase(blabla);
    lukdatabase();
}

- Ville det virke bedre hvis man brugte en class? Problemet er jo at når flere bruger programmet så bliver de til sidst timet således at databasen står åben mens en anden prøver at åbne den ..
Avatar billede nicklasw Nybegynder
06. december 2006 - 11:56 #9
tror vi misforstår hinanden lidt...
således jeg forstå på dig, er at når dit program skal skrive til databasen åbner du databasen, skriver, og lukker den...
den måde jeg **prøvet** at vise det på var at, du kun åbner databasen en gang, så ledes at den bliver åbnet når programet starter, og lukker først når programmet slutter eller du dræber class'en...

#include <iostream>
#include <string>
#include <en masse andet>

using namespace std;

class DB
{
    DB{
      //åben databasen
      }

  ~DB{
      //luk database
      }

    void skriv(string brugernavn){
      //skriv bruger info til databasen
      //brug argumentet til at finde ud hvilken bruge det er du skal skrive til
      }
}

DB database;
//nu er databasen åbnet

int main()
{
    char bruger = "nicklas";
    database.skriv(bruger);

    bruger = "michael";
    database.skriv(bruger)
    return 0;
}
//og først nu lukker databasen
Avatar billede nicklasw Nybegynder
06. december 2006 - 12:03 #10
eller for at gøre koden lidt mere pæn kan du i main() sætte nederst men før return 0;
delete database;
så den ser sådan ud.

int main()
{
    char bruger = "nicklas";
    database.skriv(bruger);

    bruger = "michael";
    database.skriv(bruger)

    delete database;
//så vi sikker på at class'en database bliver lukket
    return 0;
}
Avatar billede quiw Nybegynder
06. december 2006 - 12:34 #11
Vil lige prøve at lege med det når jeg kommer hjem, men så vidt jeg ved kan man da ikke åbne databasen og lade den stå åben og ændre så meget man vil også derefter lukke den? Kan godt være jeg har misforstået princippet i en database, men som sagt, vil prøve at lege med det når jeg kommer hjem :)
Avatar billede nicklasw Nybegynder
06. december 2006 - 12:37 #12
i msSQL og i mySQL kan man, men ved ikke med access men det vil jeg næsten tro
Avatar billede nicklasw Nybegynder
07. december 2006 - 11:59 #13
har du fået det til at virke?
Avatar billede quiw Nybegynder
08. december 2006 - 08:21 #14
Noo not really, har ikke forstand på classes så den siger fejl ved første del i klassen:
#include <iostream>
#include <string.h>
#include <sstream>
#include <windows.h>
#include <conio.h>
#include <sql.h>
#include <sqlext.h>
#include <time.h>

using namespace std;
     
      // Variables for DATABASE SYS:
      int sl;
      int outconlen; // Length of returned connection string
      char outconstr[1024]; // Returned connection string
      char sqlstr[200]; // Insert
      char *constr = "Driver={Microsoft Access Driver (*.mdb)};Dbq=database.mdb;Uid=Admin;Pwd=";
      char s[5000];
      SQLHENV Environment; //ODBC enviroment
      SQLHDBC DataBaseConnect; //ODBC Connection
      SQLHSTMT stmt; //ODBC Statement
      SQLRETURN stat; //ODBC Return status

class Database
{
      Database
      {
          stat = SQLAllocEnv(&Environment);
          if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO))
          {
                printf("Error in AllocEnv\n");
          }
          stat = SQLAllocConnect(Environment,&DataBaseConnect);
          if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO))
          {
                printf("Error in AllocConnect\n");
          }
          stat = SQLDriverConnect(DataBaseConnect,NULL,
                              (SQLCHAR *)constr,(SQLSMALLINT)strlen(constr),
                              (SQLCHAR *)outconstr, (SQLSMALLINT)sizeof(outconstr),
                              (SQLSMALLINT *)&outconlen,SQL_DRIVER_COMPLETE);
          if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO))
          {
                printf("Error in Connect\n");
          }
          stat = SQLAllocStmt(DataBaseConnect,&stmt);
          if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO))
          {
                printf("Error in AllocStmt\n");
          }
      }
     
      ~Database
      {
          SQLFreeStmt(stmt,SQL_DROP);
          SQLDisconnect(DataBaseConnect);
          SQLFreeConnect(DataBaseConnect);
          SQLFreeEnv(Environment);
      }
     
      void skriv(string brugernavn)
      {
          sprintf(sqlstr, "INSERT INTO Personer (Navn) VALUES('%s')",Brugernavn);
          stat = SQLExecDirect(stmt,(SQLCHAR *)sqlstr,strlen(sqlstr));
          if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO))
          {
                printf("Error in Write \n");
          }
          stat = SQLBindCol(stmt,1,SQL_C_CHAR,s,sizeof(s),(SQLINTEGER *)&sl);
          if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO))
          {
                printf("Error in BindCol\n");
          }
          for(;;)
          {
                stat = SQLFetch(stmt);
                if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO)) break;
                s[sl] = '\0';
          }
      }

}

int main()
{
    char bruger = "nicklas";
    Database.skriv(bruger);

    bruger = "michael";
    Database.skriv(bruger)

    delete database;
    return 0;
}
Avatar billede nicklasw Nybegynder
08. december 2006 - 11:38 #15
du skal havde () ved Database og ~Database
så det ser sådan ud ~Database() og Database()
Avatar billede nicklasw Nybegynder
08. december 2006 - 11:39 #16
undskyld glemte det i mit første eksempel
Avatar billede nicklasw Nybegynder
08. december 2006 - 11:47 #17
fandt lige nogle andre fejl i din kode her er den rettet version:

#include <iostream>
#include <string.h>
#include <sstream>
#include <windows.h>
#include <conio.h>
#include <sql.h>
#include <sqlext.h>
#include <time.h>

using namespace std;

      // Variables for DATABASE SYS:
      int sl;
      int outconlen; // Length of returned connection string
      char outconstr[1024]; // Returned connection string
      char sqlstr[200]; // Insert
      char *constr = "Driver={Microsoft Access Driver (*.mdb)};Dbq=database.mdb;Uid=Admin;Pwd=";
      char s[5000];
      SQLHENV Environment; //ODBC enviroment
      SQLHDBC DataBaseConnect; //ODBC Connection
      SQLHSTMT stmt; //ODBC Statement
      SQLRETURN stat; //ODBC Return status

class Database
{
    public:
      Database()
      {
          stat = SQLAllocEnv(&Environment);
          if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO))
          {
                printf("Error in AllocEnv\n");
          }
          stat = SQLAllocConnect(Environment,&DataBaseConnect);
          if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO))
          {
                printf("Error in AllocConnect\n");
          }
          stat = SQLDriverConnect(DataBaseConnect,NULL,
                              (SQLCHAR *)constr,(SQLSMALLINT)strlen(constr),
                              (SQLCHAR *)outconstr, (SQLSMALLINT)sizeof(outconstr),
                              (SQLSMALLINT *)&outconlen,SQL_DRIVER_COMPLETE);
          if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO))
          {
                printf("Error in Connect\n");
          }
          stat = SQLAllocStmt(DataBaseConnect,&stmt);
          if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO))
          {
                printf("Error in AllocStmt\n");
          }
      }

      ~Database()
      {
          SQLFreeStmt(stmt,SQL_DROP);
          SQLDisconnect(DataBaseConnect);
          SQLFreeConnect(DataBaseConnect);
          SQLFreeEnv(Environment);
      }

      void skriv(string brugernavn)
      {
          sprintf(sqlstr, "INSERT INTO Personer (Navn) VALUES('%s')",brugernavn);
          stat = SQLExecDirect(stmt,(SQLCHAR *)sqlstr,strlen(sqlstr));
          if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO))
          {
                printf("Error in Write \n");
          }
          stat = SQLBindCol(stmt,1,SQL_C_CHAR,s,sizeof(s),(SQLINTEGER *)&sl);
          if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO))
          {
                printf("Error in BindCol\n");
          }
          for(;;)
          {
                stat = SQLFetch(stmt);
                if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO)) break;
                s[sl] = '\0';
          }
      }

};

int main()
{
    Database DB;
    string bruger = "nicklas";
    DB.skriv(bruger);

    bruger = "michael";
    DB.skriv(bruger);

    delete DB;
    return 0;
}
Avatar billede nicklasw Nybegynder
08. december 2006 - 12:05 #18
hehe... nye fejl rettet nu skulle der ikke være flere...

#include <iostream>
#include <string.h>
#include <sstream>
#include <windows.h>
#include <conio.h>
#include <sql.h>
#include <sqlext.h>
#include <time.h>

using namespace std;

      // Variables for DATABASE SYS:
      int sl;
      int outconlen; // Length of returned connection string
      char outconstr[1024]; // Returned connection string
      char sqlstr[200]; // Insert
      char *constr = "Driver={Microsoft Access Driver (*.mdb)};Dbq=database.mdb;Uid=Admin;Pwd=";
      char s[5000];
      SQLHENV Environment; //ODBC enviroment
      SQLHDBC DataBaseConnect; //ODBC Connection
      SQLHSTMT stmt; //ODBC Statement
      SQLRETURN stat; //ODBC Return status

class Database
{
    public:
      Database()
      {
          stat = SQLAllocEnv(&Environment);
          if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO))
          {
                printf("Error in AllocEnv\n");
          }
          stat = SQLAllocConnect(Environment,&DataBaseConnect);
          if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO))
          {
                printf("Error in AllocConnect\n");
          }
          stat = SQLDriverConnect(DataBaseConnect,NULL,
                              (SQLCHAR *)constr,(SQLSMALLINT)strlen(constr),
                              (SQLCHAR *)outconstr, (SQLSMALLINT)sizeof(outconstr),
                              (SQLSMALLINT *)&outconlen,SQL_DRIVER_COMPLETE);
          if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO))
          {
                printf("Error in Connect\n");
          }
          stat = SQLAllocStmt(DataBaseConnect,&stmt);
          if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO))
          {
                printf("Error in AllocStmt\n");
          }
      }

      ~Database()
      {
          SQLFreeStmt(stmt,SQL_DROP);
          SQLDisconnect(DataBaseConnect);
          SQLFreeConnect(DataBaseConnect);
          SQLFreeEnv(Environment);
      }

      void skriv(char *brugernavn)
      {
          sprintf(sqlstr, "INSERT INTO Personer (Navn) VALUES('%s')",brugernavn);
          stat = SQLExecDirect(stmt,(SQLCHAR *)sqlstr,strlen(sqlstr));
          if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO))
          {
                printf("Error in Write \n");
          }
          stat = SQLBindCol(stmt,1,SQL_C_CHAR,s,sizeof(s),(SQLINTEGER *)&sl);
          if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO))
          {
                printf("Error in BindCol\n");
          }
          for(;;)
          {
                stat = SQLFetch(stmt);
                if((stat!=SQL_SUCCESS)&&(stat!=SQL_SUCCESS_WITH_INFO)) break;
                s[sl] = '\0';
          }
      }

};

int main()
{
    Database DB;
    char *bruger = "nicklas";
    DB.skriv(bruger);

    bruger = "michael";
    DB.skriv(bruger);

    return 0;
}
Avatar billede quiw Nybegynder
22. december 2006 - 18:56 #19
Well .. Det ser ud til at virke, jeg lavede et loop som skrev 10.000 beskeder i databasen, den fuldførte det på et par sekunder .. Uden at brokke sig :) Så ser ud til at virke, men ser hvordan det kommer til at virke i mit spil :)

- Smid lige et svar :)
Avatar billede nicklasw Nybegynder
22. december 2006 - 19:01 #20
svar
glad for at kunne hjælpe
Avatar billede nicklasw Nybegynder
22. december 2006 - 19:02 #21
ups svar
Avatar billede quiw Nybegynder
22. december 2006 - 19:04 #22
Mange Tak :)
- Tænkte på, hvorfor er det bedre at bruge class i stedet for en almindelig void funktion?
Avatar billede nicklasw Nybegynder
22. december 2006 - 19:14 #23
fordi det er mere overskueligt (min mening)
Men det er ikke rigtig pointen, lige i den her sitiation.
grunden til at din database crashede var fordi at når du skulle skrive til databasen så gjorde du sådan her.

programmet starter
åben DB
skriv DB
luk DB

åben DB
skriv DB
luk DB

åben DB
skriv DB
luk DB
osv.

programmet lukker

det belaster den ret meget, i steden for den måde du, nu, gør det på er.

programmet starter

opretter class

class'en lave en forbindelse til databasen

skriv db
skriv db
skriv db
skriv db osv.

sletter den oprettet class
det starter ~db functionen
der lukker forbindelsen
og så lukker programmet

det belaster databasen meget mindre
Avatar billede nicklasw Nybegynder
22. december 2006 - 19:15 #24
du må lige sige til hvis du ikke forstår det...
har nemlig lidt svært ved at forklare det, men vil da gerne prøve igen hvis det fuldstændigt ulæseligt ;)
Avatar billede nicklasw Nybegynder
22. december 2006 - 19:20 #25
du kan se at vi kun køre de to led der hedder åben db og luk db en gang, mens før gjorde du det hver gang du skulle skrive i db'en
Avatar billede quiw Nybegynder
22. december 2006 - 19:23 #26
Yeah I see .. Men har bare ikke forstået hvorfor en class kan holde databasen åben mens et void ikke kan .. Ved void skal man åbne og skrive og lukke .. Ved en class kan man åbne, skrive, skrive, skrive og lukke ..
Avatar billede nicklasw Nybegynder
22. december 2006 - 19:35 #27
det er objektiv programmering, prøv at læs lidt om det, det er et ekstremt stærkt værktøj.

men skal prøve at forklare det.

koden i main() der ser sådan ud
Database DB;
"kalder" den class du har skrevet, det vil sige den loader den ind i memory'en.
automatisk når du kalder class'en starter den functionen Database() det åbner connection... nu har du et objekt der er loaded in i memoryen og tilgænglig indtil du lukker objektet igen, det kan du gøre med "kill" functionen, eller lukke programmet.
det er det der gør forskellen...

men du kan tilføje mig på msn eller skype hvis det er... så skal jeg nok prøve at forklare det bedere
Avatar billede quiw Nybegynder
22. december 2006 - 20:54 #28
Quiw@jubiipost.dk :)
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
Kurser inden for grundlæggende programmering

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