2015-05-29 13 views
14

Sto utilizzando una connessione ODBC per recuperare i dati da un file di Access (.mdb) in un ambiente Unity3D (Mono.net) su Windows 7 e la connessione, la deconnessione e le richieste avvengono senza errori.Perché l'accesso MS odbc restituisce numeri ma non stringhe in C#?

Ma quando ho letto i dati che ottengo, ricevo solo i numeri dal database. Può essere numeri interi o float. Ma quando provo a recuperare una stringa, restituisce sempre una stringa vuota.

Ecco quello che uso nella mia classe DataBaseHandler per eseguire le richieste (estratti):

public ArrayList Execute(string req) 
{ 
ArrayList output = new ArrayList(); 

[...] 

cmd = new OdbcCommand(req); 
cmd.Connection = accessConnection; 

OdbcDataReader reader = cmd.ExecuteReader(); 
while (reader.Read()) { 
    String[] row = new String[reader.FieldCount]; 

    for (int i=0; i<reader.FieldCount; i++) { 
     if (!reader.IsDBNull(i)) { // Added if for Visual Studio 
      // Getting empties strings, but work fine with numbers 
      row[i] = reader.GetValue(i).ToString(); 
      // I was using GetString before, but didn't work with Visual Studio 
     } 
    } 

    output.Add(row); 
} 

[...] 
return output; 
} 

e questo è quello che mi esibisco per testare la richiesta:

ArrayList data = db.Execute("SELECT * FROM Materials"); 

foreach (String[] row in data) { 
    string line = ""; 
    foreach (String s in row) { 
     line += s + " - "; 
    } 
    Debug.Log(line); // Logging in Unity3D console 
} 

e sto ottenendo :

1234 - 23.1 - - - 
5678 - 12.9 - - - 

Invece di:

01.235.
1234 - 23.1 - A string - Another string - 
5678 - 12.9 - Hello - World - 

Perché sto ricevendo solo numeri e senza stringhe e come posso correggerlo?

MODIFICA: Funziona bene con Visual Studio 12 e Windows 7 e le modifiche che dovevo apportare per far funzionare il prodotto con Visual Studio non mostravano alcun miglioramento nel mio programma Unity.

+1

Se si inserisce un Debug.Log (s); all'interno del tuo recinto foreach esce qualcosa? – wvisaacs

+2

Un paio di cose, Non usare 'ArrayList' usa' Lista ', usa un punto di debug e esegui il debug passo dopo passo, il tuo secondo frammento di codice dovrebbe funzionare bene, il problema è dove stai popolando il tuo' ArrayList' * (prima snippet di codice) * – Habib

+0

Il 'Debug.Log' già nel foreach restituisce qualcosa come" 302912 - - - 32.1 - - 64 - 50 ". Salta le corde. Stesso risultato con 'Elenco ' ma userò i punti di interruzione e vedrò cosa succede – Dean

risposta

0

Penso che si usi DataSet anziché DataReader Durante la lettura dei dati dai database di Access!

0

ci sono alcune cattive pratiche di codifica [string line = ""; string line = String.Empty;] lì

Emettere tutto riga prima della seconda istruzione foreach. vedi il tuo problema

1

Devo iniziare dicendo che non ho un ambiente per riprodurlo; la mia risposta è molto basata su ciò che ho speso in C# su Windows con SQL Server; vale a dire che i buffer utilizzati sotto il DataReader vengono riutilizzati per l'efficienza della memoria.

Quando i numeri vengono convertiti in stringhe, la memoria DEVE essere allocata per la stringa, poiché attualmente non esiste alcuna stringa. Quando ToString viene eseguito su una stringa effettiva, probabilmente stai ricevendo un riferimento a una stringa ancora nascosta in profondità all'interno di DataReader. Quella memoria viene quindi riutilizzata dal record successivo.

La soluzione di base è eseguire l'elaborazione su base record o eseguire copie di tutto ciò di cui si ha bisogno mentre si esegue il ciclo.

0

È necessario utilizzare GetString(columnOrdinal) method dove columnOrdinal è la colonna della stringa basata su zero.

È necessario essere specifici sul tipo di colonne restituite quando si utilizza ODBC. Quindi nel tuo caso lo sarebbe.

public ArrayList Execute(string req) 
{ 
ArrayList output = new ArrayList(); 

[...] 

cmd = new OdbcCommand(req); 
cmd.Connection = accessConnection; 

OdbcDataReader reader = cmd.ExecuteReader(); 
while (reader.Read()) { 
    String[] row = new String[reader.FieldCount]; 

    for (int i=0; i<reader.FieldCount; i++) { 
     if (!reader.IsDBNull(i)) { // Added if for Visual Studio 

      if (i > 0 && i < 2) 
      { 
       row[i] = reader.GetInt32(i); 
      } 
      else 
      { 
       row[i] = reader.GetString(i); 
      } 
     } 
    } 

    output.Add(row); 
} 

[...] 
return output; 
} 

Altrimenti credo GetValue restituisce un oggetto null.