Odpowiedzi:
var reader = cmd.ExecuteReader();
var columns = new List<string>();
for(int i=0;i<reader.FieldCount;i++)
{
columns.Add(reader.GetName(i));
}
lub
var columns = Enumerable.Range(0, reader.FieldCount).Select(reader.GetName).ToList();
columns = Enumerable.Range(0, reader.FieldCount) .Select(reader.GetName).ToList();
SELECT id AS "MyId" FROM table;
Istnieje GetName
funkcja, SqlDataReader
która akceptuje indeks kolumny i zwraca nazwę kolumny.
I odwrotnie, istnieje taki, GetOrdinal
który pobiera nazwę kolumny i zwraca indeks kolumny.
GetOrdinal
było perfekcyjne. Szukałem GetName
, ale o wiele czystszego rozwiązania mojego problemu z GetOrdinal
.
Nazwy kolumn można uzyskać z czytnika danych.
Oto ważna część:
for (int col = 0; col < SqlReader.FieldCount; col++)
{
Console.Write(SqlReader.GetName(col).ToString()); // Gets the column name
Console.Write(SqlReader.GetFieldType(col).ToString()); // Gets the column type
Console.Write(SqlReader.GetDataTypeName(col).ToString()); // Gets the column database type
}
Już wspomniane. Tylko odpowiedź LINQ :
var columns = reader.GetSchemaTable().Rows
.Cast<DataRow>()
.Select(r => (string)r["ColumnName"])
.ToList();
//Or
var columns = Enumerable.Range(0, reader.FieldCount)
.Select(reader.GetName)
.ToList();
Drugi jest czystszy i znacznie szybszy. Nawet jeśli buforujesz GetSchemaTable
w pierwszym podejściu, zapytania będą bardzo powolne.
reader.Cast<IDataRecord>().ToList()
. Uważam, że możesz użyć dynamic
słowa kluczowego zamiast, IDataRecord
ale bez korzyści. DataTable
został zaprojektowany, aby ułatwić jednorazowe ładowanie, więc możesz z niego skorzystać, ale tracisz korzyści z ładowania na żądanie (z czytnikiem danych możesz zatrzymać ładowanie w dowolnym momencie), na przykład var dt = new DataTable(); dt.Load(reader); return dt.AsEnumerable().ToList();
. Istnieje wiele bibliotek, które mogą zautomatyzować to za Ciebie, znajdź je tutaj stackoverflow.com/questions/11988441 i tutaj stackoverflow.com/questions/1464883
reader.Cast<IEnumerable<dynamic>>
i .Cast<dynamic>
, ale mówi, Cannot convert method group 'Cast' to non-delegate type 'dynamic'. Did you intend to invoke the method?
co zrobiłem tam źle? (Spojrzałem na twoje źródła, ale wymagały od ciebie nazwy kolumny, której nie znam)
Jeśli chcesz tylko nazwy kolumn, możesz:
List<string> columns = new List<string>();
using (SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly))
{
DataTable dt = reader.GetSchemaTable();
foreach (DataRow row in dt.Rows)
{
columns.Add(row.Field<String>("ColumnName"));
}
}
Ale jeśli potrzebujesz tylko jednego wiersza, podoba mi się mój dodatek AdoHelper. Ten dodatek jest świetny, jeśli masz jednowierszowe zapytanie i nie chcesz zajmować się tabelą danych w swoim kodzie. Zwraca słownik nazw i wartości kolumn bez rozróżniania wielkości liter.
public static Dictionary<string, string> ExecuteCaseInsensitiveDictionary(string query, string connectionString, Dictionary<string, string> queryParams = null)
{
Dictionary<string, string> CaseInsensitiveDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
try
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand())
{
cmd.Connection = conn;
cmd.CommandType = CommandType.Text;
cmd.CommandText = query;
// Add the parameters for the SelectCommand.
if (queryParams != null)
foreach (var param in queryParams)
cmd.Parameters.AddWithValue(param.Key, param.Value);
using (SqlDataReader reader = cmd.ExecuteReader())
{
DataTable dt = new DataTable();
dt.Load(reader);
foreach (DataRow row in dt.Rows)
{
foreach (DataColumn column in dt.Columns)
{
CaseInsensitiveDictionary.Add(column.ColumnName, row[column].ToString());
}
}
}
}
conn.Close();
}
}
catch (Exception ex)
{
throw ex;
}
return CaseInsensitiveDictionary;
}
throw ex;
jest najgorszą praktyką.
Korzystam z metody GetSchemaTable , która jest udostępniana przez interfejs IDataReader.
Użyj metody rozszerzenia:
public static List<string> ColumnList(this IDataReader dataReader)
{
var columns = new List<string>();
for (int i = 0; i < dataReader.FieldCount; i++)
{
columns.Add(dataReader.GetName(i));
}
return columns;
}
Na pewno możesz.
protected void GetColumNames_DataReader()
{
System.Data.SqlClient.SqlConnection SqlCon = new System.Data.SqlClient.SqlConnection("server=localhost;database=northwind;trusted_connection=true");
System.Data.SqlClient.SqlCommand SqlCmd = new System.Data.SqlClient.SqlCommand("SELECT * FROM Products", SqlCon);
SqlCon.Open();
System.Data.SqlClient.SqlDataReader SqlReader = SqlCmd.ExecuteReader();
System.Int32 _columncount = SqlReader.FieldCount;
System.Web.HttpContext.Current.Response.Write("SqlDataReader Columns");
System.Web.HttpContext.Current.Response.Write(" ");
for ( System.Int32 iCol = 0; iCol < _columncount; iCol ++ )
{
System.Web.HttpContext.Current.Response.Write("Column " + iCol.ToString() + ": ");
System.Web.HttpContext.Current.Response.Write(SqlReader.GetName( iCol ).ToString());
System.Web.HttpContext.Current.Response.Write(" ");
}
}
Pochodzi z: http://www.dotnetjunkies.ddj.com/Article/B82A22D1-8437-4C7A-B6AA-C6C9BE9DB8A6.dcik