Risposte:
var reader = cmd.ExecuteReader();
var columns = new List<string>();
for(int i=0;i<reader.FieldCount;i++)
{
columns.Add(reader.GetName(i));
}
o
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;
C'è una GetName
funzione sulla SqlDataReader
quale accetta l'indice di colonna e restituisce il nome della colonna.
Al contrario, esiste un oggetto GetOrdinal
che accetta un nome di colonna e restituisce l'indice di colonna.
GetOrdinal
era perfetto. Stavo cercando GetName
, ma una soluzione molto più pulita per il mio problema con GetOrdinal
.
È possibile ottenere i nomi delle colonne da un DataReader.
Ecco la parte importante:
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
}
Già menzionato. Solo una risposta 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();
Il secondo è più pulito e molto più veloce. Anche se si memorizza GetSchemaTable
nella cache il primo approccio, l'interrogazione sarà molto lenta.
reader.Cast<IDataRecord>().ToList()
. Credo che potresti usare la dynamic
parola chiave lì invece di IDataRecord
ma senza alcun vantaggio. DataTable
è stato progettato per facilitare il caricamento in tempo, quindi è possibile utilizzarlo anche ma si perde il vantaggio del caricamento su richiesta (con il lettore di dati è possibile interrompere il caricamento in qualsiasi momento), ad esempio var dt = new DataTable(); dt.Load(reader); return dt.AsEnumerable().ToList();
. Ci sono molte librerie che possono automatizzare questo per voi, trovarli qui stackoverflow.com/questions/11988441 e qui stackoverflow.com/questions/1464883
reader.Cast<IEnumerable<dynamic>>
e .Cast<dynamic>
, ma dice, Cannot convert method group 'Cast' to non-delegate type 'dynamic'. Did you intend to invoke the method?
cosa ho fatto di sbagliato lì? (Ho esaminato le tue fonti, ma ti hanno richiesto di conoscere il nome della colonna, cosa che io non conosco)
Se vuoi solo i nomi delle colonne, puoi fare:
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"));
}
}
Ma se hai bisogno solo di una riga, mi piace la mia aggiunta AdoHelper. Questa aggiunta è ottima se si dispone di una query a riga singola e non si desidera gestire la tabella di dati nel codice. Restituisce un dizionario senza distinzione tra maiuscole e minuscole di nomi e valori di colonne.
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;
è la peggiore pratica.
Uso il metodo GetSchemaTable , che è esposto tramite l'interfaccia IDataReader.
Utilizzare un metodo di estensione:
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;
}
Sicuro che puoi.
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(" ");
}
}
Questo è originariamente da: http://www.dotnetjunkies.ddj.com/Article/B82A22D1-8437-4C7A-B6AA-C6C9BE9DB8A6.dcik