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

时间:2010-11-08 17:40:50

标签: c# ado.net

只有在IDataRecord中存在field_name时才有更好的方法从IDataRecord获取field_name值,目前我正在使用 try {...} catch {...} 阻止,但这是某种 On Error Resume next 。一些替代方案?

/// <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);
}

4 个答案:

答案 0 :(得分:16)

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

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方法首先对名称进行大小写搜索,如果失败,则会进行一个案例的本能搜索。这不是由字典提供的,所以如果你想要那个确切的行为,你宁愿将名字存储在数组中,并在你想要找到索引时编写一个循环遍历它们的方法。

答案 1 :(得分:2)

看看这个密切相关的问题,找出一个可行的方法来测试一个领域的存在。请注意,如果要迭代结果集合,最好先检查一次列,而不是每次迭代。

Check for column name in a SqlDataReader object

答案 2 :(得分:2)

有一行:

public ActionResult Edit(int? id)
{
    if (id == null)
    {
        throw new HttpException(400, "Bad request");
    }
    Contract contract = business.Get<Contract>(x => x.IdContract == id);
    ContractViewModel vm = new ContractViewModel(contract);
    if (contract == null)
    {
        throw new HttpException(404, "Not found");
    }            
    return View(vm);
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(ContractViewModel vm)
{
    Contract contract = business.Get<Contract>(x => x.IdContract == id);
    if (ModelState.IsValid)
    {
        [...]
    }
    return View(vm);
}

public ActionResult AddDocument(int id)
{
    DocumentViewModel vm = new DocumentViewModel();
    vm.IdContract = id;
    return PartialView(vm);
}

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult AddDocument(DocumentViewModel vm)
{
    Contract contract = business.Get<Contract>(x => x.IdContract == vm.IdContract);            
    if (ModelState.IsValid)
    {
        [...]
    }
    return RedirectToAction("Edit", "Contracts", new { id = vm.IdContract });
    //return View(vm);
}

答案 3 :(得分:1)

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

当然,如果您有一个真正的IDataRecord,那么如果您尝试将其投放到IDataReader并且它不是一个,则会失败。