Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 15
  1. #1

    Problema nel prelevare dati dal database access

    Dunque, ho un piccolo problema relativo al casting.

    Per un'elaborazione dati ad un certo punto faccio una select che mi restituisce il count(*) di quante righe ha una determinata tabella.

    Il database è access e lo uso come file diretto e non come ODBC.

    Il procedimento è che mi creo per prima cosa tre oggetti:

    System.Data.OleDb.OleDbCommand cmd;
    System.Data.OleDb.OleDbConnection conn;
    System.Data.OleDb.OleDbDataReader read;

    Nel costruttore della mia classe imposto la connectionstring di conn.

    Nel metodo che deve fare questa operazione per prima cosa setto

    cmd.CommandText=query;

    dove query è la query select che mi serve, poi eseguo l'struzione

    read = cmd.ExecuteReader();

    e subito

    read.Read();

    per spostarmi sulla prima ed unica righa risultato.

    Dunque, vorrei piazzare il risultato contenuto nella prima ed unica colonna della riga in una variabile i di tipo Int64.

    Penserete che forse con Int64 mi sono allargato, ma non avete idea di quante righe sono

    La prima cosa che ho tentato è stata questa:

    i = read.GetInt64(0);

    Neanche a dirlo mi da errore di Cast errato...

    Allora provo:

    i = (Int64)read.GetValue(0)

    Altra bestemmie sul Cast.

    Altra prova.

    i = (Int64)read.GetString(0)

    Niente...

    Il discorso è questo, per estrapolare il valore del campo ho due scelte:

    O so esattamente di che tipo è e quindi so quali cast posso fare (se mi servono) e se li posso fare.

    O rimetto tutto a lui usando GetValue, in questo modo lo prendo nel formato nativo; però, così facendo lo devo per forza convertire in stringa e piazzarlo in una stringa, come segue:

    String appoggio = read.GetValue(0).toString();

    Solo che dopo, se era un numero, non ho idea di come riconvertirlo in numero da una stringa, perchè fra i metodi String non trovo nulla in proposito e i cast non funzionano...

    Ho scoperto con l'istruzione

    String tipo=read.GetValue(0).GetType().toString();

    che il valore che esce è in realtà un Int32.

    Però, se era un int16 invece? O un int64?

    Qualcuno di voi sa dirmi quindi come fare un'estrazione da db in base al contenuto del campo?

    Grazie

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,463
    Onestamente, non capisco da dove deriva il problema. :master:

    Quando ottieni i dati di una query attraverso un DataReader, il tipo di dato con cui effettuare il "casting" per memorizzarlo o trattarlo è quello che più si avvicina al tipo attribuito al campo stesso all'interno del database.

    Se hai a disposizione un campo data/ora, lo leggerai come DateTime; se hai a disposizione un intero con un Int32 e così via.
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  3. #3
    Premetto che ho risolto, cmq il problema era che io non ero a conoscenza del campo che usciva in virtù del fatto che era il risultato di un count(*).

    Più grande sarebbe stato il risultato, maggiore era il tipo di dato, poteva essere Int16, 32 o 64.

    Il modo in cui l'ho risolta è questo:

    Int64 i = Int64.Parse(read.GetValue(0).toString());

    Così funziona al 100%, a prescindere dalla grandezza del numero e quindi del tipo che esce.


    Ciao!

  4. #4
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,463
    Originariamente inviato da Debiru
    Più grande sarebbe stato il risultato, maggiore era il tipo di dato, poteva essere Int16, 32 o 64.
    Siamo sicuri? Ho il sospetto che invece il tipo sia sempre Int32. :master:
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  5. #5
    Utente di HTML.it L'avatar di U235
    Registrato dal
    Mar 2006
    Messaggi
    1,536
    Originariamente inviato da Debiru
    Premetto che ho risolto, cmq il problema era che io non ero a conoscenza del campo che usciva in virtù del fatto che era il risultato di un count(*).

    Più grande sarebbe stato il risultato, maggiore era il tipo di dato, poteva essere Int16, 32 o 64.

    Il modo in cui l'ho risolta è questo:

    Int64 i = Int64.Parse(read.GetValue(0).toString());

    Così funziona al 100%, a prescindere dalla grandezza del numero e quindi del tipo che esce.


    Ciao!
    ma sei proprio sicuro che per contare il numero dei record (cosi' mi sembra di capire :master: ) non ti basti un Int16 o un Int32 ma ti serve veramente un Int64?

    credo che si squaglierebbe prima il db o il pc dell' Int32
    poi va beh tutto è possibile in questo mondo, pero'...


    Per curiosità cosa è un db con il censimento delle formiche?!? Le stelle?!? peli e capelli umani e non?!?



  6. #6
    Guarda, ti dico solo che era una sola tabella con la bellezza di 465.000 record e rotti, ora un 16bit non ce la faceva, un 32 andava bene, ma io volevo provare a fare un'applicazione con un margine ancor più alto... tutto quì


    Cmq con quel sistema ho risolto.

  7. #7
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,463
    Originariamente inviato da Debiru
    Guarda, ti dico solo che era una sola tabella con la bellezza di 465.000 record e rotti, ora un 16bit non ce la faceva, un 32 andava bene, ma io volevo provare a fare un'applicazione con un margine ancor più alto... tutto quì
    Secondo me, hai fatto un ragionamento sbagliato sugli errori che hai ottenuto.

    Il fatto che non venga usato un Int16 non significa necessariamente che il tipo di dato cambi a seconda del numero restituito come conteggio dei record.

    Hai risolto il problema, ma a mio avviso hai inserito codice sostanzialmente inutile poiché, se è vero che il conteggio restituito è sempre e comunque un valore Int32, non ha senso gestire diversi tipi di dati: è sufficiente usare appunto il tipo Int32 esplicitamente e l'operazione va sempre a buon fine.

    In sostanza, quando la query ti restituisce il conteggio di record, restituisce un valore Int32 e come tale va reperito il dato dal "result set" ottenuto.

    Poi, onestamente, non so quale margine più alto vuoi arrivare a trattare visto che un Int32 può contarti fino ad un massimale di oltre 2 miliardi, una quantità di record che non penso arriverai a trattare comunque.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  8. #8
    Utente di HTML.it L'avatar di U235
    Registrato dal
    Mar 2006
    Messaggi
    1,536
    Originariamente inviato da alka
    Secondo me, hai fatto un ragionamento sbagliato sugli errori che hai ottenuto.

    Il fatto che non venga usato un Int16 non significa necessariamente che il tipo di dato cambi a seconda del numero restituito come conteggio dei record.

    Hai risolto il problema, ma a mio avviso hai inserito codice sostanzialmente inutile poiché, se è vero che il conteggio restituito è sempre e comunque un valore Int32, non ha senso gestire diversi tipi di dati: è sufficiente usare appunto il tipo Int32 esplicitamente e l'operazione va sempre a buon fine.

    In sostanza, quando la query ti restituisce il conteggio di record, restituisce un valore Int32 e come tale va reperito il dato dal "result set" ottenuto.

    Poi, onestamente, non so quale margine più alto vuoi arrivare a trattare visto che un Int32 può contarti fino ad un massimale di oltre 2 miliardi, una quantità di record che non penso arriverai a trattare comunque.

    Ciao!
    ciao alka,
    a parer mio hai pienamente ragione, magari lui potrebbe voler fare (ipotesi banale) una moltiplicazione in runtime del risultato di diverse interrogazioni arrivando quindi a cifre astronomiche, quindi onde evitare l'over pone tutto in un Int64, ma dal suo cod. non mi sembra sia cosi' e poi non mi è ancora chiaro se il risultato lo ottiene ciclando e contando uno per uno oppure è un interrogazione al db, sembrerebbe quasi che conti ogni record aggiungendo il valore del campo al conteggio (e non +1) ma in questo caso comunque andrebbe ad aggiungere sempre un Int32 a un Int64 creato per contenere dei valori molto alti.

    Debiru per favore inluminami

  9. #9
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,463
    La query era una SELECT COUNT, quindi non ci sono operazioni complesse in gioco, ma un semplice conteggio dei record di una tabella.

    Dal mio punto di vista, si legge con un Int32, senza fare ricorso a tipi di dati più semplici o più complessi.
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  10. #10
    E invece vi aggiorno perchè la situazione è ancora più complessa di quanto pensavo.

    Allora, qualsiasi sia il numero che restituisce la count viene interpretato come un Int32.

    Anche nel caso sia inferiore al range massimo di un Int16...

    Allora ho voluto fare delle prove, creare delle circostanze per cui il count restituisse un valore superiore al MaxValue di Int32 (lo so, non ho un ca**o da fare).

    In access, prima di farlo da codice, ho testato una query effettuando una select count due volte sulla stessa tabella senza creare join (select count(*) from tabella as t1, tabella as t2).

    In questo modo, in base alla logica di prodotto cartesiano, mi sarebbe uscito un valore altissimo...

    E' morto access.

    Devo dire che di tempo per elaborare glie ne ho dato, tipo 30-40 minuti e io ho un athlon xp 2800+ 64bit con 1gb di ram...

    Forse access non ce la fa fisicamente a superare simili count(), ma non mi stupirei, vista la cattiva fama di access...

    Ma siccome, ripeto, non avevo un C da fare ho tirato in ballo anche MySql.

    Dopo bestemmie su bestemmie per creare una connessione con il db MySql ce l'ho fatta, e vi dico pure come ci si collega, dovesse essere utile a qualcuno.

    Per prima cosa ho utilizzato il sistema ODBC, quindi oltre ad installare MySql occorre installare il pacchetto di driver ODBC dal sito del MySql (altrimenti non si può creare il DSN tramite gli Strumenti di Amministrazione).

    Una volta che ho creato ed impostato un DSN utente, ad esempio MySql, basta che creo i tre oggetti cardine sulla mia classe

    System.Data.Odbc.OdbcConnection conn;
    System.Data.Odbc.OdbcCommand cmd;
    System.Data.Odbc.OdbcDataReader read;

    Mi basta poi inizializzare conn e settare la sua ConnectionString = "DSN=MySql" e il gioco è fatto.

    La prima cosa che ho fatto è stato appurare che tipo di dato restituisce il count() con MySql e quì c'è stato il colpo di scena.

    MySql gestisce il count come un Int64

    Quindi, come dice Alka, si, è vero che restituisce sempre un campo dello stesso tipo, ma se si cambia DBMS non è garantito che il tipo sia sempre lo stesso...

    Quindi diciamo che in fin dei conti C# da degli standard abbastanza facili da usare con qualsiasi DBMS, se poi vogliamo la vita facile basta che per ogni DBMS creiamo un DSN allora si potrebbe anche fare cambi tattici di DBMS senza rimettere mano al codice, ma nel caso di utilizzo di count o roba simile allora sarebbe un problema...

    Che ne dite?

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.