2 Stimmen

SqlDataReader-Spalten-Ordinale

Angenommen, ich rufe eine Abfrage "SELECT name, city, country FROM People" auf. Sobald ich meinen SqlDataReader ausführe, kommen die Spalten in der gleichen Reihenfolge wie in meiner Sql-Abfrage?

Mit anderen Worten: Kann ich mich darauf verlassen, dass der folgende Code immer korrekt 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 Leistung verliere ich, wenn ich Spaltennamen anstelle von Ordnungszahlen (reader["name"]) verwenden?

Gibt es irgendwelche offiziellen Microsoft-Dokumente, die das Verhalten der Spaltenanordnung in SqlDataReader beschreiben?

5voto

Josh Punkte 66190

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

Was die Leistung anbelangt, so denke ich, dass sie im Vergleich zum Overhead beim Abrufen der nächsten Datenzeile wahrscheinlich äußerst unbedeutend ist.

5voto

marc_s Punkte 701497

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

ABER: Ich würde immer noch die Spaltennamen bevorzugen, da sie robuster sind. Was ist z. B., wenn Sie ein Feld zu Ihrer SQL-Abfrage hinzufügen müssen?

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

Jetzt müssen Sie plötzlich Ihren gesamten Code neu schreiben, um die Positionen zu ändern....

Was ich normalerweise außerhalb der Schleife tue, die alle vom Datenleser zurückgegebenen Zeilen aufzählt, ist die Bestimmung der Positionen der einzelnen Felder, an denen ich interessiert bin:

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

und dann verwende ich diese Positionen in meiner Schleife zur Verarbeitung der Daten, um schnellen Zugriff auf die einzelnen Felder zu erhalten. Auf diese Weise bestimmen Sie die Positionen nur einmal, aber Sie verwenden die Positionen in Ihrer Schleife über die Daten - das Beste aus beiden Welten! :-)

Marc

4voto

Harvo Jones Punkte 41

Dieses Beispiel ist am pflegeleichtesten und am einfachsten zu lesen:

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

Sie stützt sich auf die folgende von mir erstellte Erweiterungsmethode. Sie führt DB-Null-Prüfungen durch, liefert eine informative Fehlermeldung, wenn ein Feld nicht gefunden wird, und bricht nicht ab, wenn 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);
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X