只有在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);
}
答案 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)
看看这个密切相关的问题,找出一个可行的方法来测试一个领域的存在。请注意,如果要迭代结果集合,最好先检查一次列,而不是每次迭代。
答案 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
并且它不是一个,则会失败。