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 GetNamefunkcja, SqlDataReaderktóra akceptuje indeks kolumny i zwraca nazwę kolumny.
I odwrotnie, istnieje taki, GetOrdinalktóry pobiera nazwę kolumny i zwraca indeks kolumny.
GetOrdinalbył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 GetSchemaTablew pierwszym podejściu, zapytania będą bardzo powolne.
reader.Cast<IDataRecord>().ToList() . Uważam, że możesz użyć dynamicsłowa kluczowego zamiast, IDataRecordale bez korzyści. DataTablezostał 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