SqlDataReader Spalten Ordinals

Angenommen, ich rufe eine Abfrage "SELECT Name, Stadt, Land von Menschen". Sobald ich meine SqlDataReader ausführen, treten Spalten in der gleichen Reihenfolge wie in meiner SQL-Abfrage?

Mit anderen Worten, ich kann mich darauf verlassen, dass der folgende Code immer richtig funktioniert:

SqlConnection connection = new SqlConnection(MyConnectionString); SqlCommand command = new SqlCommand(); command.Connection = connection; command.CommandText = "SELECT [name], [city], [country] WHERE [id] = @id"; try { connection.Open(); SqlDataReader reader = command.ExecuteReader(System.Data.CommandBehavior.SingleRow); if (reader.Read()) { // Read values. name = reader[0].ToString(); city = reader[1].ToString(); country = reader[2].ToString(); } } catch (Exception) { throw; } finally { connection.Close(); } 

Auch wie viel performance verliere ich, wenn ich Spaltennamen anstelle von Ordinals verwende (Leser ["name"])?

Gibt es offizielle Microsoft-Dokumente, die das Verhalten der Spaltenordnung in SqlDataReader beschreiben?

Ja, aber Sie können auch SqlDataReader.GetName (Ordinal) und SqlDataReader.GetOrdinal (Name) verwenden.

Wie für die performance, denke ich, es ist wahrscheinlich extrem unbedeutend im Vergleich zu den Overhead zu sagen, die Wiederholung der nächsten Zeile der data.

Ich stimme voll mit Josh – die Positionen der Felder sind in der Tat so, wie Sie sie in Ihrem SQL-Abfragetext angeben.

ABER: Ich würde lieber die Spaltennamen verwenden, da es robuster ist. ZB, was ist, wenn Sie ein Feld zu Ihrer SQL-Abfrage hinzufügen müssen?

 command.CommandText = "SELECT [name], [jobtitle], [city], [country] WHERE [id] = @id"; 

Jetzt musst du plötzlich deinen ganzen Code umschreiben, um die Positionen zu ändern ….

Was ich normalerweise außerhalb der loop mache, die durch alle Zeilen, die vom dataleser zurückgegeben werden, aufzählt, bestimmen die Positionen jedes Feldes, an dem ich interessiert bin:

 int namePosition = reader.GetOrdinal("name"); int cityPosition = reader.GetOrdinal("city"); 

und dann benutze ich diese Positionen in meiner loop, die die data verarbeitet, um schnellen Zugriff auf die einzelnen Felder zu erhalten. Auf diese Weise bestimmen Sie die Positionen nur einmal, aber Sie verwenden Positionen in Ihrem Looping über die data – das Beste aus beiden Welten! 🙂

Marc

Dieses Beispiel ist das pflegeleichteste und einfachste zu lesen:

 int? quantity = reader.Get<int?>("Quantity"); Guid token = reader.Get<Guid>("Token"); 

Es beruht auf der folgenden Erweiterungsmethode, die ich erstellt habe. Es führt DB-Null-Prüfungen durch, liefert eine informative Fehlermeldung, wenn das Feld nicht gefunden wird und nicht brechen wird, wenn die Spalten neu ausgerichtet werden.

 internal static T Get<T>(this SqlDataReader reader, string fieldName) { int ordinal; try { ordinal = reader.GetOrdinal(fieldName); } catch (IndexOutOfRangeException) { throw new IndexOutOfRangeException(string.Format("Field name '{0}' not found.", fieldName)); } return !reader.IsDBNull(ordinal) ? (T)reader.GetValue(ordinal) : default(T); } 

Prost,

Harvo