如何将数据读取器转换为动态查询结果

我有一个View通常从WebMatrix查询( IEnumerable数据类型)获取查询结果,并在表中显示结果:

 @model MySite.Models.Entity @foreach(var row in Model.Data) {  @foreach (var column in row.Columns) { @column: @row[column] }  } 

这是我查询数据库的模型:

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

以下是我在阅读其他各种post时尝试过的所有不同内容:

  // 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; // Error: 'Cannot convert method group "Cast" to non-delegate type "dynamic". Did you intend to invoke the method? // Atempt 3 Data = reader.Cast<IEnumerable>; // Error same as Atempt 2 // Atempt 4 Data = reader.Cast<IEnumerable>; // Error same as Atempt 2 } } } } 

我正在寻找将读者对象转换为IEnumerable对象的最佳方法。

请注意这是一个简化的示例,虽然两种查询类型的原因并不明显,但在我的代码中它们是必需的。

您缺少基本的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; // 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>; // Cast method itself returns an IEnumerable. // You dont have to cast individual rows to IEnumerable Data = reader.Cast>; // Meaningless I believe. // The data you get from database is not always strings 

你犯的主要错误是不调用方法。 这就是你想要的:

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

您可以通过多种方式进行此操作,具体取决于更容易处理(例如,在前端显示)。

  1. 返回数据记录。

     public IEnumerable 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。 也许这就是你想要的?

     public IEnumerable 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; foreach (var name in names) expando[name] = record[name]; yield return expando; } } } 
  3. 属性包的返回顺序

     public IEnumerable> 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. 返回普通对象数组的序列

     public IEnumerable> 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. 返回数据行

     public IEnumerable 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. 最后但并非最不重要的是,如果有帮助,您可以返回强类型序列而无需任何手动管道。 您可以使用表达式树在运行时编译代码。 见例如

尝试循环读者结果:

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

看起来你只是试图将一个对象设置为command.ExecuteReader();的未执行的IQueriable结果。