2015-07-27 5 views
6

Ho una visione che ottiene in genere i risultati delle query da un WebMatrix Query (IEnumerable<dynamic> tipo di dati), e visualizza i risultati in una tabella:Come convertire un lettore di dati per query dinamica risultati

@model MySite.Models.Entity 
@foreach(var row in Model.Data) 
{ 
    <tr> 
     @foreach (var column in row.Columns) 
     { 
      <td>@column<span>:</span> @row[column]</td> 
     } 
    </tr> 
} 

Ecco il mio modello dove ho interrogare il database:

public class Entity 
{ 
    public dynamic Data {get; set; } 
    public Entity(String table) 
    { 
     if (table == "User" || table == "Group) 
     { 
      WebMatrix.Data.Database db = new WebMatrix.Data.Database(); 
      db.Open(ConString); 
      Data = db.Query("SELECT * FROM " + table); 
     } 
     else 
     { 
      using (OdbcConnection con = ne4w OdbcConnection(ConString)) 
      { 
       OdbcCommand com = new OdbcCommand("Select * From " + table); 
       command.CommandType = System.Data.CommandType.Text; 
       connection.Open(); 
       OdbcDataReader reader = command.ExecuteReader(); 

Ecco tutte le cose diverse che ho provato dalla lettura di vari altri posti:

   // Atempt 1 
       Data = reader; 
       // Error in view, 'Invalid attempt to call FieldCount when reader is closed' (on 'var row `in` Model.Data') 

       // Atempt 2 
       Data = reader.Cast<dynamic>; 
       // Error: 'Cannot convert method group "Cast" to non-delegate type "dynamic". Did you intend to invoke the method? 

       // Atempt 3 
       Data = reader.Cast<IEnumerable<dynamic>>; 
       // Error same as Atempt 2 

       // Atempt 4 
       Data = reader.Cast<IEnumerable<string>>; 
       // Error same as Atempt 2 
      } 
     } 
    } 
} 

Sto cercando il modo migliore per ottenere l'oggetto lettore su un oggetto IEnumerable<dynamic>.

Si prega di notare che questo è un esempio semplificato, e mentre il motivo per i due tipi di query non è ovvio, sono necessari nel mio codice.

+0

Domanda correlata: http: // stackoverflow.it/questions/15211437/how-to-read-dynamic-properties-from-database – nawfal

risposta

20

Ti manca la sintassi di base in C#.

Data = reader; 
// You cant do this. You have to loop the reader to get the values from it. 
// If you simply assign reader object itself as the data you wont be 
// able to get data once the reader or connection is closed. 
// The reader is typically closed in the method. 

Data = reader.Cast<dynamic>; 
// You should call the Cast method. And preferably execute the resulting query. 
// As of now you're merely assigning method reference to a variable 
// which is not what you want. 
// Also bear in mind that, as I said before there's no real benefit in casting to dynamic 

Data = reader.Cast<IEnumerable<dynamic>>; 
// Cast method itself returns an IEnumerable. 
// You dont have to cast individual rows to IEnumerable 

Data = reader.Cast<IEnumerable<string>>; 
// Meaningless I believe. 
// The data you get from database is not always strings 

Il principale errore si può fare e non chiamando il metodo. Questo è ciò che si vuole:

Data = reader.Cast<IDataRecord>().ToList(); 
           ^^ // notice the opening and closing parentheses 

Si potrebbe andare su questo un certo numero di modi a seconda di ciò che è più facile da processo (per esempio, per visualizzare in front-end).

  1. Dati di ritorno.

    public IEnumerable<IDataRecord> SelectDataRecord() 
    { 
        .... 
    
        using (var reader = cmd.ExecuteReader()) 
         foreach (IDataRecord record in reader as IEnumerable) 
          yield return record; //yield return to keep the reader open 
    } 
    
  2. ExpandoObjects ritorno. Forse questo è quello che volevi? sequenza

    public IEnumerable<dynamic> SelectDynamic() 
    { 
        .... 
    
        using (var reader = cmd.ExecuteReader()) 
        { 
         var names = Enumerable.Range(0, reader.FieldCount).Select(reader.GetName).ToList(); 
         foreach (IDataRecord record in reader as IEnumerable) 
         { 
          var expando = new ExpandoObject() as IDictionary<string, object>; 
          foreach (var name in names) 
           expando[name] = record[name]; 
    
          yield return expando; 
         } 
        } 
    } 
    
  3. ritorno del sacchetto struttura

    public IEnumerable<Dictionary<string, object>> SelectDictionary() 
    { 
        .... 
    
        using (var reader = cmd.ExecuteReader()) 
        { 
         var names = Enumerable.Range(0, reader.FieldCount).Select(reader.GetName).ToList(); 
         foreach (IDataRecord record in reader as IEnumerable) 
          yield return names.ToDictionary(n => n, n => record[n]); 
        } 
    } 
    
  4. sequenza ritorno della matrice oggetto pianura

    public IEnumerable<List<object>> SelectObjectArray() 
    { 
        .... 
    
        using (var reader = cmd.ExecuteReader()) 
        { 
         var indices = Enumerable.Range(0, reader.FieldCount).ToList(); 
         foreach (IDataRecord record in reader as IEnumerable) 
          yield return indices.Select(i => record[i]).ToList(); 
        } 
    } 
    
  5. righe di dati di ritorno

    public IEnumerable<DataRow> SelectDataRow() 
    { 
        .... 
    
        using (var reader = cmd.ExecuteReader()) 
        { 
         var table = new DataTable(); 
         table.BeginLoadData(); 
         table.Load(reader); 
         table.EndLoadData(); 
         return table.AsEnumerable(); // in assembly: System.Data.DataSetExtensions 
        } 
    } 
    
  6. Ultimo ma non meno importante, se aiuta, è possibile restituire una sequenza fortemente tipizzata senza alcun impianto idraulico manuale. È possibile utilizzare gli alberi di espressione per compilare il codice in fase di esecuzione. Vedere this per es.

+0

come qualcuno potrebbe creare una versione 'async' della seconda opzione? L'ho provato e continuo a ricevere il seguente errore: 'Il corpo di DbHelper.GetDataFromSproc (stringa sprocName, dizionario parametri) 'non può essere un blocco iteratore perché' Attività > 'non è un tipo di interfaccia iteratore' – Code

+0

@Code vedere questo thread: http://stackoverflow.com/questions/23295119/asynchronous-iterator-taskienumerablet – nawfal

0

Prova loop i risultati del lettore:

OdbcDataReader reader = command.ExecuteReader(); 

while(reader.Read()) 
{ 
    var item = reader["yourField"].ToString(); 
} 

Sembra che si sta solo cercando di impostare un oggetto per il risultato IQueriable non eseguita della Command.ExecuteReader();