Відповіді:
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