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

C# ADO.Net:检查IDataRecord上是否存在字段名,c#,ado.net,C#,Ado.net,只有当IDataRecord中存在字段名时,才有更好的方法从IDataRecord获取字段名值,目前我使用的是try{…}catch{…}块,但这是某种错误。有其他选择吗 /// <summary> /// Returns column value from IDataRecord only if field_name exists. /// </summary> public static Tresult ValueIfExists<Tresult>(thi

只有当IDataRecord中存在字段名时,才有更好的方法从IDataRecord获取字段名值,目前我使用的是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));
}
//
///仅当字段_name存在时,才从IDataRecord返回列值。
/// 
public static Tresult ValueIfExists(此IDataRecord记录,字符串字段\ U名称)
{
请尝试{return record.Value(record.GetOrdinal(field_name));}
catch{返回默认值(Tresult);}
}
/// 
///按索引从IDataRecord返回列值。
/// 
公共静态Tresult值(此IDataRecord记录,int字段_索引)
{
返回记录.IsDBNull(字段索引)?默认值(Tresult):
(Tresult)Convert.ChangeType(记录[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);
}
public static Tresult ValueIfExists2(此IDataRecord记录,字符串字段\u名称)
{
for(int index=0;index
看看这个密切相关的问题,寻找一种可行的测试字段存在性的方法。请注意,如果要迭代一组结果,最好只检查一次列,而不是每次迭代


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

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;
}
公共静态字典getAllName(此IDataRecord记录){
var result=newdictionary();
对于(int i=0;i
您可以使用
ContainsKey
方法检查字典中是否存在该名称,或者使用
TryGetValue
方法检查该名称是否存在,并获取它在单个操作中的索引


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

对于
IDataReader
(因为您得到的大多数
IDataRecord
都是读卡器)
reader.GetSchemaTable().Columns.Contains(“字段”)

当然,如果您有一个正版的
IDataRecord
,那么如果您尝试将其转换为
IDataReader
,并且它不是一个,则此操作将失败。

只有一行:

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

我认为[IDataRecord]接口缺少用于测试元素存在性的方法。我曾使用过类似于Visual Basic 6记录集的代码,但我认为.Net已经有了处理此问题的工具。@ArceBrito:据我所知,也没有方法专门检查实现类(如
SqlDataReader
)中字段的存在性。你只需要使用
GetName
来找出有哪些字段。更为关键的版本是:
Enumerable.Range(0,record.FieldCount)。ToDictionary(i=>record.GetName(i),i=>i)
这意味着目前检查[IDataRecord]接口中字段存在的唯一方式是迭代。然后问题是实现IDataRecord的最佳搜索算法。在我的例子中,我使用映射器模式通过传递IDataRecord作为参数来创建对象,因此我不能使用您建议的方法;另一方面,它需要获取数据库表元数据,这可能比为了检查字段是否存在而对字段集合进行迭代更为昂贵,实际上通常更便宜。在
SQLDataReader
的情况下,元数据至少被抓取一次,然后被缓存,因此它只会继续读取相同的变量。这会检查模式表中的列,而不是实际的数据表!总是返回错误!检查此答案:您应该使用
StringComparison.OrdinalIgnoreCase
作为列名,列名在任何情况下都可以。可能的重复项