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