После подключения к базе данных, могу ли я получить имена всех столбцов, которые были возвращены в моем SqlDataReader?
Можете ли вы получить имена столбцов из SqlDataReader?
Ответы (10)
На SqlDataReader есть функция GetName, которая принимает индекс столбца и возвращает имя столбца.
И наоборот, есть GetOrdinal, который принимает имя столбца и возвращает индекс столбца.
GetOrdinal был идеальным. Я искал GetName, но гораздо более чистое решение моей проблемы с GetOrdinal.
- person goodeye; 30.07.2015
Вы можете получить имена столбцов из 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
- person nawfal; 27.07.2015
reader.Cast<IEnumerable<dynamic>> и .Cast<dynamic>, но там написано: Cannot convert method group 'Cast' to non-delegate type 'dynamic'. Did you intend to invoke the method? что я там сделал не так? (Я просмотрел ваши источники, но они требовали, чтобы вы знали имя столбца, чего я не знаю)
- person Travis Heeter; 27.07.2015
using (var reader = command.ExecuteReader()) { return reader.Cast<IDataRecord>().ToList(); } . См. Этот ответ для общего преобразования в объекты expando: stackoverflow.com/a/20223709/661933
- person nawfal; 27.07.2015
Если вам нужны только имена столбцов, вы можете сделать:
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; - наихудшая практика.
- person asawyer; 08.03.2017
Используйте метод расширения:
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;
}
Для меня я бы написал такой метод расширения:
public static string[] GetFieldNames(this SqlDataReader reader)
{
return Enumerable.Range(0, reader.FieldCount).Select(x => reader.GetName(x)).ToArray();
}
Я использую метод GetSchemaTable, который предоставляется через интерфейс IDataReader.
Вы конечно можете.
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
Это проще сделать в SQL
var columnsList = dbContext.Database.SqlQuery<string>("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = 'SCHEMA_OF_YOUE_TABLE' AND TABLE_NAME = 'YOUR_TABLE_NAME'").ToList();
columns = Enumerable.Range(0, reader.FieldCount) .Select(reader.GetName).ToList();
- person Alex; 23.05.2013
SELECT id AS "MyId" FROM table;
- person styfle; 13.07.2013