Réponses:
var reader = cmd.ExecuteReader();
var columns = new List<string>();
for(int i=0;i<reader.FieldCount;i++)
{
columns.Add(reader.GetName(i));
}
ou
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;
Il y a une GetName
fonction sur le SqlDataReader
qui accepte l'index de colonne et retourne le nom de la colonne.
Inversement, il y a un GetOrdinal
qui prend un nom de colonne et retourne l'index de colonne.
GetOrdinal
était parfait. Je cherchais GetName
, mais une solution beaucoup plus propre pour mon problème GetOrdinal
.
Vous pouvez obtenir les noms de colonne à partir d'un DataReader.
Voici la partie 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
}
Déjà mentionné. Juste une réponse 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();
Le second est plus propre et beaucoup plus rapide. Même si vous mettez en cache GetSchemaTable
dans la première approche, l'interrogation va être très lente.
reader.Cast<IDataRecord>().ToList()
. Je pense que vous pouvez utiliser un dynamic
mot clé à la place, IDataRecord
mais sans aucun avantage. DataTable
a été conçu pour faciliter le chargement ponctuel, vous pouvez donc l'utiliser aussi mais vous perdez l'avantage du chargement à la demande (avec le lecteur de données, vous pouvez arrêter le chargement à tout moment), comme var dt = new DataTable(); dt.Load(reader); return dt.AsEnumerable().ToList();
. Il existe de nombreuses bibliothèques qui peuvent automatiser cela pour vous, trouvez-les ici stackoverflow.com/questions/11988441 et ici stackoverflow.com/questions/1464883
reader.Cast<IEnumerable<dynamic>>
et .Cast<dynamic>
, mais ça dit, Cannot convert method group 'Cast' to non-delegate type 'dynamic'. Did you intend to invoke the method?
qu'est-ce que j'ai fait de mal là-bas? (J'ai regardé vos sources, mais elles vous demandaient de connaître le nom de la colonne, ce que je ne sais pas)
Si vous ne voulez que les noms de colonne, vous pouvez faire:
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"));
}
}
Mais si vous n'avez besoin que d'une seule ligne, j'aime mon ajout AdoHelper. Cet ajout est idéal si vous avez une requête sur une seule ligne et que vous ne souhaitez pas traiter le tableau de données dans votre code. Il renvoie un dictionnaire insensible à la casse des noms et des valeurs des colonnes.
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;
est une pire pratique.
J'utilise la méthode GetSchemaTable , qui est exposée via l'interface IDataReader.
Utilisez une méthode d'extension:
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;
}
Vous le pouvez certainement.
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(" ");
}
}
Il s'agit à l'origine de: http://www.dotnetjunkies.ddj.com/Article/B82A22D1-8437-4C7A-B6AA-C6C9BE9DB8A6.dcik