Ответы:
var reader = cmd.ExecuteReader();
var columns = new List<string>();
for(int i=0;i<reader.FieldCount;i++)
{
columns.Add(reader.GetName(i));
}
или
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;
Существует GetName
функция, SqlDataReader
которая принимает индекс столбца и возвращает имя столбца.
И наоборот, есть, GetOrdinal
который принимает имя столбца и возвращает индекс столбца.
GetOrdinal
было прекрасно. Я искал GetName
, но гораздо более чистое решение для моей проблемы с GetOrdinal
.
Вы можете получить имена столбцов из DataReader.
Вот важная часть:
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
}
Уже упоминалось. Просто ответ 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();
Второй чище и намного быстрее. Даже если вы кешируете GetSchemaTable
при первом подходе, запросы будут очень медленными.
reader.Cast<IDataRecord>().ToList()
. Я считаю, что вы могли бы использовать dynamic
ключевое слово там, IDataRecord
но без пользы. DataTable
был разработан, чтобы облегчить однократную загрузку, так что вы можете использовать это тоже, но вы теряете преимущество загрузки по требованию (с помощью считывателя данных вы можете прекратить загрузку в любой момент), например var dt = new DataTable(); dt.Load(reader); return dt.AsEnumerable().ToList();
. Есть много библиотек, которые могут автоматизировать это для вас, найдите их здесь stackoverflow.com/questions/11988441 и здесь stackoverflow.com/questions/1464883
reader.Cast<IEnumerable<dynamic>>
и .Cast<dynamic>
, но там написано, Cannot convert method group 'Cast' to non-delegate type 'dynamic'. Did you intend to invoke the method?
что я там не так сделал? (Я посмотрел на ваши источники, но они потребовали, чтобы вы знали имя столбца, а я нет)
Если вы хотите только имена столбцов, вы можете сделать:
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"));
}
}
Но если вам нужен только один ряд, мне нравится мое дополнение AdoHelper. Это дополнение хорошо, если у вас есть однострочный запрос, и вы не хотите иметь дело с таблицей данных в своем коде. Он возвращает нечувствительный к регистру словарь имен и значений столбцов.
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;
это худшая практика.
Я использую метод GetSchemaTable , который предоставляется через интерфейс IDataReader.
Используйте метод расширения:
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;
}
Вы уверены, что можете.
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(" ");
}
}
Это родом из: http://www.dotnetjunkies.ddj.com/Article/B82A22D1-8437-4C7A-B6AA-C6C9BE9DB8A6.dcik