ADO.Net:检查 IDataRecord 上是否存在字段名称

发布于 2024-10-01 08:45:24 字数 1326 浏览 2 评论 0原文

仅当 IDataRecord 中存在 field_name 时,是否有更好的方法从 IDataRecord 获取 field_name 值,目前我正在使用 try{...} catch{...} 块,但是这是某种下一步错误恢复。一些替代方案?

/// <summary>
/// Returns column value from IDataRecord only if field_name exists.
/// </summary>
public static Tresult ValueIfExists<Tresult>(this IDataRecord record, string field_name)
{
    try { return record.Value<Tresult>(record.GetOrdinal(field_name)); }
    catch { return default(Tresult); }
}

/// <summary>
/// Returns column value from IDataRecord accecing by index.
/// </summary>
public static Tresult Value<Tresult>(this IDataRecord record, int field_index)
{
    return record.IsDBNull(field_index) ? default(Tresult) :
              (Tresult)Convert.ChangeType(record[field_index], typeof(Tresult));
}

我更改了我的 ValueIfExists 函数来反映您的想法,所以它看起来像这样:

public static Tresult ValueIfExists2<Tresult>(this IDataRecord record, string field_name)
{
    for (int index = 0; index < record.FieldCount; index++)
    {
        if (record.GetName(index).Equals(field_name, StringComparison.InvariantCulture))
        {
            return record.Value<Tresult>(record.GetOrdinal(field_name));
        }
    }
    return default(Tresult);
}

Is there a better way for getting the field_name value from a IDataRecord only if the field_name exists in the IDataRecord, currently I'm using a try{...} catch{...} block, but this is some kind of On Error Resume next. Some alternatives?

/// <summary>
/// Returns column value from IDataRecord only if field_name exists.
/// </summary>
public static Tresult ValueIfExists<Tresult>(this IDataRecord record, string field_name)
{
    try { return record.Value<Tresult>(record.GetOrdinal(field_name)); }
    catch { return default(Tresult); }
}

/// <summary>
/// Returns column value from IDataRecord accecing by index.
/// </summary>
public static Tresult Value<Tresult>(this IDataRecord record, int field_index)
{
    return record.IsDBNull(field_index) ? default(Tresult) :
              (Tresult)Convert.ChangeType(record[field_index], typeof(Tresult));
}

I have changed my ValueIfExists function to reflect your ideas, so it looks like this:

public static Tresult ValueIfExists2<Tresult>(this IDataRecord record, string field_name)
{
    for (int index = 0; index < record.FieldCount; index++)
    {
        if (record.GetName(index).Equals(field_name, StringComparison.InvariantCulture))
        {
            return record.Value<Tresult>(record.GetOrdinal(field_name));
        }
    }
    return default(Tresult);
}

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

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

发布评论

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

评论(4

梦幻之岛 2024-10-08 08:45:24

您是对的,异常不应该用于正常的程序流程。

GetOrdinal 方法适用于以下情况:您知道所获取的字段,并且如果缺少某个字段,则该字段是一个错误,会导致异常。

如果您不知道结果中包含哪些字段,则应避免使用 GetOrdinal 方法。您可以将所有名称及其索引放入字典中,以替换 GetOrdinal 方法:

public static Dictionary<string, int> GetAllNames(this IDataRecord record) {
  var result = new Dictionary<string, int>();
  for (int i = 0; i < record.FieldCount; i++) {
    result.Add(record.GetName(i), i);
  }
  return result;
}

您可以使用 ContainsKey 方法来检查名称是否存在在字典中,或使用 TryGetValue 方法检查名称是否存在并在单个操作中获取其索引。

GetOrdinal 方法首先对名称进行区分大小写的搜索,如果失败,则进行不区分大小写的搜索。字典没有提供这一点,因此如果您想要确切的行为,您宁愿将名称存储在数组中,并在想要查找索引时编写一个方法来循环遍历它们。

You are right that exceptions should not be used for normal program flow.

The GetOrdinal method is intended for situations where you know what fields you get, and if a field is missing that is an error that should result in an exception.

If you don't know which fields you get in the result, you should avoid the GetOrdinal method. You can instead get all the names and their index into a dictionary that you can use as replacement for the GetOrdinal method:

public static Dictionary<string, int> GetAllNames(this IDataRecord record) {
  var result = new Dictionary<string, int>();
  for (int i = 0; i < record.FieldCount; i++) {
    result.Add(record.GetName(i), i);
  }
  return result;
}

You can use the ContainsKey method to check if the name exists in the dictionary, or the TryGetValue method to check if the name exists and get it's index it does in a single operation.

The GetOrdinal method first does a case sensetive search for the name, and if that fails it does a case insensetive search. That is not provided by the dictionary, so if you want that exact behaviour you would rather store the names in an array and write a method to loop through them when you want to find the index.

心安伴我暖 2024-10-08 08:45:24

用一行:

bool exists = Enumerable.Range(0, dataRecord.FieldCount).Any(x => dataRecord.GetName(x) == "columnName"); // or with OrdinalIgnoreCase

With one line:

bool exists = Enumerable.Range(0, dataRecord.FieldCount).Any(x => dataRecord.GetName(x) == "columnName"); // or with OrdinalIgnoreCase
说好的呢 2024-10-08 08:45:24

看一下这个密切相关的问题,了解测试字段是否存在的可行方法。请注意,如果您要迭代结果集合,最好检查一次列,而不是每次迭代。

检查 SqlDataReader 对象中的列名称

Take a look at this closely-related question for a viable approach of testing for a field's existence. Note that if you are iterating a collection of results, it is probably better to check for the column once, rather than on each iteration.

Check for column name in a SqlDataReader object

彩扇题诗 2024-10-08 08:45:24

我总是对 IDataReader 使用以下方法(因为您获得的大多数 IDataRecord 都是读者)
reader.GetSchemaTable().Columns.Contains("field")

当然,如果您有一个真正的 IDataRecord 那么如果您尝试将其转换为 则会失败IDataReader 但它不是一个。

I always use the following approach for IDataReader (since most IDataRecord you get are readers)
reader.GetSchemaTable().Columns.Contains("field")

Of course if you have a genuine IDataRecord then this will fail if you try to cast it to IDataReader and it isn't one.

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