2015-07-27 6 views
6

ich eine Ansicht, die typischerweise Abfrage-Ergebnisse aus einer WebMatrix Query (IEnumerable<dynamic> Datentyp), und zeigt die Ergebnisse in einer Tabelle erhält:Wie ein Datenlesegerät, um dynamische Abfrage zu konvertieren führt

@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> 
} 

Hier ist mein Modell wo ich die Datenbank abfragen:

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(); 

Hier ist all die verschiedenen Dinge, die ich aus der Lektüre verschiedenen anderen Beiträgen versucht haben:

   // 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 
      } 
     } 
    } 
} 

Ich bin auf der Suche nach dem besten Weg, um das Leserobjekt zu einem IEnumerable<dynamic> Objekt zu bekommen.

Bitte beachten Sie, dies ist ein vereinfachtes Beispiel, und während der Grund für die beiden Abfragetypen nicht offensichtlich ist, sind sie in meinem Code erforderlich.

+0

Verwandte Frage: http: // Stackoverflow.com/questions/15211437/how-to-read-dynamic-Eigenschaften-from-database – nawfal

Antwort

20

Sie vermissen grundlegende C# -Syntax.

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 

Der größte Fehler, den Sie machen, ist die Methode nicht aufrufen. Dies ist, was Sie wollen:

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

Sie dazu auf eine Reihe von Möglichkeiten gehen könnte je nachdem, was zu Prozess einfacher ist (sagen wir, in Frontend angezeigt werden).

  1. Rücksendung von Datensätzen.

    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. Zurück ExpandoObjects. Vielleicht wollten Sie das?

    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. Rückreihenfolge von Eigentum Beutel

    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. Return-Sequenz von einfachen Objektarray

    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. Datenrück Reihen

    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. Last but not least, wenn es hilft, können Sie eine stark typisierte Sequenz ohne manuelle Installation zurückgeben. Sie können mithilfe von Ausdrucksbäumen Code zur Laufzeit kompilieren. Siehe this für z.B.

+0

Wie würde jemand eine 'async'-Version der zweiten Option erstellen? Ich habe es ausprobiert und bekomme folgenden Fehler: 'Der Body von DbHelper.GetDataFromSproc (String sprocName, Dictionary Parameter) 'kann kein Iterator sein, weil' Task > 'kein Iterator Interface Typ' ist – Code

+0

@Code siehe diesen Thread: http://stackoverflow.com/questions/23295119/asynchronous-iterator-taskienumerablet – nawfal

0

Versuchen Sie, die Leser Ergebnisse Looping:

OdbcDataReader reader = command.ExecuteReader(); 

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

Es sieht aus wie Sie gerade versuchen, ein Objekt in den unausgeführt IQueriable Ergebnis Command.ExecuteReader zu setzen();