IDataReader.GetOrdinal 或 IDataReader[ColumnName]

发布于 2025-01-06 12:14:08 字数 531 浏览 2 评论 0原文

我有两种情况从 IDataReader 对象中提取信息

Case - 1 - Length,计算序数,然后解析字符串

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

Case - 2,简短的方式,获取数据而不计算序数

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

应该首选哪种技术以及为什么以及是否有特定上下文?

I have two cases to extract information from the IDataReader object

Case - 1 - Length, calculates ordinal and then parse string

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

Case - 2, short way, getting data without calculating ordinal

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

Which technique should be preferred and why and if any specific context ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

残月升风 2025-01-13 12:14:08

SqlDataReader的 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;
}

SqlDataReader's this[string name] looks like:

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

so it calculates ordinal internaly, and there is no difference what way to use.

UPDATE

Yo can rewrite your code as:

public static string GetString(IDataReader rdr, string columnName)
{
    return (rdr[columnName] as String)??String.Empty;
}
咿呀咿呀哟 2025-01-13 12:14:08

这是第一种方法的 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

所以这些方法肯定不一样。至于哪个更好,您没有说明为什么要计算序数,因此很难说哪个更适合您的情况。

Here's what MSIL looks like for your first method:

.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

And for your second method:

.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

So the methods are definitely not the same. As to which is better, you don't say why you want to calculate the ordinal so it's hard to say which is better for your situation.

指尖上得阳光 2025-01-13 12:14:08

我不认为真的有什么区别(他们做同样的事情),第二个对我来说似乎更具可读性,因为“索引”的引入会让那些不知道读者如何工作的人感到困惑。我说隐藏不必要的复杂性。您应该更进一步,使其成为可以在任何地方使用的泛型,如下所示:

    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");

编辑:
您没有在第二个示例中检查 DBNull,因此转换会因空值而失败。然而,一般来说,这两种方法是相同的。

I don't think there's really a difference (they do the same thing), the second seems more readable to me as the introduction of the 'index' is confusing for those who don't know how the reader is working. Hide needless complexity I say. You should go a step further and make it a generic you can use anywhere, like this:

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

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

        return (T)value;
    }

Invoking it is easy:

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

Edit:
You're not checking for DBNull in your second example, so the cast would fail on nulls. However, generally speaking the two approaches are the same.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文