IDataReader.GetOrdinal или IDataReader [ColumnName] - PullRequest
3 голосов
/ 16 февраля 2012

У меня есть два случая, чтобы извлечь информацию из объекта IDataReader

Case - 1 - длина, вычисляет порядковый номер и затем разбирает строку

public static string GetString(IDataReader rdr, string columnName)
{
    int ordinal = rdr.GetOrdinal(columnName);
    if (rdr.IsDBNull(ordinal))
    {
        return string.Empty;
    }
    return (string)rdr[ordinal];
}

Случай - 2, короткий путь, получение данных без вычисления порядкового номера

public static string GetString(IDataReader rdr, string columnName)
{
    return (string)rdr[columnName];
}

Какой метод должен быть предпочтительным и почему, и если какой-либо конкретный контекст?

Ответы [ 3 ]

4 голосов
/ 16 февраля 2012

SqlDataReader's this[string name] выглядит следующим образом:

public override object this[string name]
{
    get
    {
        return this.GetValue(this.GetOrdinal(name));
    }
}

, поэтому он вычисляет внутренний порядок, и нет никакой разницы, какой способ использовать.

ОБНОВЛЕНИЕ

Йо может переписать ваш код как:

public static string GetString(IDataReader rdr, string columnName)
{
    return (rdr[columnName] as String)??String.Empty;
}
2 голосов
/ 16 февраля 2012

Вот как выглядит MSIL для вашего первого метода:

.method public hidebysig static string  GetString(class [System.Data]System.Data.IDataReader rdr,
                                                  string columnName) cil managed
{
  // Code size       49 (0x31)
  .maxstack  2
  .locals init ([0] int32 ordinal,
           [1] string CS$1$0000,
           [2] bool CS$4$0001)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  ldarg.1
  IL_0003:  callvirt   instance int32 [System.Data]System.Data.IDataRecord::GetOrdinal(string)
  IL_0008:  stloc.0
  IL_0009:  ldarg.0
  IL_000a:  ldloc.0
  IL_000b:  callvirt   instance bool [System.Data]System.Data.IDataRecord::IsDBNull(int32)
  IL_0010:  ldc.i4.0
  IL_0011:  ceq
  IL_0013:  stloc.2
  IL_0014:  ldloc.2
  IL_0015:  brtrue.s   IL_0020
  IL_0017:  nop
  IL_0018:  ldsfld     string [mscorlib]System.String::Empty
  IL_001d:  stloc.1
  IL_001e:  br.s       IL_002f
  IL_0020:  ldarg.0
  IL_0021:  ldloc.0
  IL_0022:  callvirt   instance object [System.Data]System.Data.IDataRecord::get_Item(int32)
  IL_0027:  castclass  [mscorlib]System.String
  IL_002c:  stloc.1
  IL_002d:  br.s       IL_002f
  IL_002f:  ldloc.1
  IL_0030:  ret
} // end of method Program::GetString

И для вашего второго метода:

.method public hidebysig static string  GetStringShort(class [System.Data]System.Data.IDataReader rdr,
                                                       string columnName) cil managed
{
  // Code size       18 (0x12)
  .maxstack  2
  .locals init ([0] string CS$1$0000)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  ldarg.1
  IL_0003:  callvirt   instance object [System.Data]System.Data.IDataRecord::get_Item(string)
  IL_0008:  castclass  [mscorlib]System.String
  IL_000d:  stloc.0
  IL_000e:  br.s       IL_0010
  IL_0010:  ldloc.0
  IL_0011:  ret
} // end of method Program::GetStringShort

Так что методы определенно не одинаковы.Что касается того, что лучше, вы не говорите, почему вы хотите вычислить порядковый номер, поэтому трудно сказать, что лучше для вашей ситуации.

0 голосов
/ 16 февраля 2012

Я не думаю, что на самом деле есть разница (они делают то же самое), второе кажется мне более читабельным, так как введение «указателя» сбивает с толку тех, кто не знает, как работает читатель. Спрячьте ненужную сложность, говорю я. Вы должны сделать шаг вперед и сделать его универсальным, который вы можете использовать где угодно, например так:

    private static T FromDbValue<T>(IDataReader rdr, string columnName)
    {
        var value = rdr[columnName];

        if (value == DBNull.Value)
        {
            return default(T);
        }

        return (T)value;
    }

Вызов это легко:

var someString = FromDbValue<string>(rdr, "CustomerName");

Edit: Вы не проверяете DBNull во втором примере, поэтому приведение не будет выполнено для нулей. Однако, вообще говоря, два подхода одинаковы.

...